Changeset 238939 in webkit


Ignore:
Timestamp:
Dec 6, 2018 1:22:19 PM (5 years ago)
Author:
Wenson Hsieh
Message:

[iOS] WKWebView should match UITextView behavior when editing text with an RTL keyboard
https://bugs.webkit.org/show_bug.cgi?id=187554
<rdar://problem/42075638>

Reviewed by Tim Horton.

Source/WebKit:

Add support for automatically switching the base writing direction to the default writing direction with respect
to the current keyboard in an editable WKWebView by implementing -setBaseWritingDirection:forRange:. On iOS 12
and earlier, UIKit invokes this protocol method whenever the keyboard is changed to one with a different writing
direction, although in some other versions of iOS, this only happens when first focusing an editable area.

Test: editing/input/ios/rtl-keyboard-input-on-focus.html

  • Platform/spi/ios/UIKitSPI.h:

Declare UIKeyboardImpl IPI methods mostly for use in WebKitTestRunner (with the exception of
-setInitialDirection, which we may invoke when we receive the first post-layout EditorState update after
focusing an editable element).

  • UIProcess/PageClient.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::increaseListLevel):
(WebKit::WebPageProxy::decreaseListLevel):
(WebKit::WebPageProxy::changeListType):
(WebKit::WebPageProxy::setBaseWritingDirection):

Drive-by style fixes: make these bail and return early if !isValid().

(WebKit::WebPageProxy::resetStateAfterProcessExited):

Reset assisted node state in the UI process upon web process termination.

  • UIProcess/WebPageProxy.h:

Add plumbing for setBaseWritingDirection, from WebPageProxy to WebPage to Editor.

  • UIProcess/ios/PageClientImplIOS.h:
  • UIProcess/ios/PageClientImplIOS.mm:

(WebKit::PageClientImpl::didReceiveEditorStateUpdateAfterFocus):

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

(-[WKContentView baseWritingDirectionForPosition:inDirection:]):
(coreWritingDirection):
(-[WKContentView setBaseWritingDirection:forRange:]):

Support -setBaseWritingDirectionForPosition:forRange:, but only in the case where the given range is the
selected range. This is all that's currently needed to fulfill the requirements in <rdar://problem/42075638>,
though we could potentially add full support for this in the future by mapping the given text range to a DOM
range and moving the selection prior to setting the base writing direction.

(-[WKContentView _didReceiveEditorStateUpdateAfterFocus]):

Add a hook to notify WKContentView when the first post-layout EditorState has been received in the UI process.
When this is invoked, if the web view is editable and the selection is not a range, we call into UIKeyboardImpl
to change the initial writing direction if necessary.

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::startAssistingNode):
(WebKit::WebPageProxy::stopAssistingNode):
(WebKit::WebPageProxy::editorStateChanged):

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::setBaseWritingDirection):

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

Tools:

Add support for simulating the keyboard input mode in layout tests using UIScriptController, as well as a new
TestOption to make the web view editable.

  • DumpRenderTree/ios/UIScriptControllerIOS.mm:

(WTR::UIScriptController::setKeyboardInputModeIdentifier):

  • TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
  • TestRunnerShared/UIScriptContext/UIScriptController.cpp:

(WTR::UIScriptController::setKeyboardInputModeIdentifier):

  • TestRunnerShared/UIScriptContext/UIScriptController.h:
  • WebKitTestRunner/PlatformWebView.h:
  • WebKitTestRunner/TestController.cpp:

(WTR::updateTestOptionsFromTestHeader):

  • WebKitTestRunner/TestController.h:

(WTR::TestController::overriddenKeyboardInputMode const):

  • WebKitTestRunner/TestOptions.h:

(WTR::TestOptions::hasSameInitializationOptions const):

  • WebKitTestRunner/cocoa/TestControllerCocoa.mm:

(WTR::TestController::platformCreateWebView):

  • WebKitTestRunner/gtk/PlatformWebViewGtk.cpp:

(WTR::PlatformWebView::setEditable):

  • WebKitTestRunner/ios/PlatformWebViewIOS.mm:

(WTR::PlatformWebView::setEditable):

  • WebKitTestRunner/ios/TestControllerIOS.mm:

(WTR::TestController::platformResetStateToConsistentValues):
(WTR::swizzleCurrentInputMode):
(WTR::TestController::setKeyboardInputModeIdentifier):

Swizzle out several UIKeyboardInputModeController methods in order to convince UIKit that the user has
selected a UIKeyboardInputMode corresponding to the given identifier. The call to
-prepareKeyboardInputModeFromPreferences: is also necessary on iOS 12 in order to update cached writing
direction state in UIKit.

  • WebKitTestRunner/ios/UIScriptControllerIOS.mm:

(WTR::UIScriptController::setKeyboardInputModeIdentifier):

  • WebKitTestRunner/mac/PlatformWebViewMac.mm:

(WTR::PlatformWebView::setEditable):

  • WebKitTestRunner/win/PlatformWebViewWin.cpp:

(WTR::PlatformWebView::setEditable):

  • WebKitTestRunner/wpe/PlatformWebViewWPE.cpp:

(WTR::PlatformWebView::setEditable):

LayoutTests:

Add a new layout test to verify that when focusing an editable WKWebView using a right-to-left keyboard input
mode, we will set the base writing direction to be right-to-left, and vice versa.

  • TestExpectations:
  • editing/input/ios/rtl-keyboard-input-on-focus-expected.txt: Added.
  • editing/input/ios/rtl-keyboard-input-on-focus.html: Added.
  • platform/ios-wk2/TestExpectations:
  • resources/ui-helper.js:

Add a UIHelper method to set the keyboard input mode to the given identifier. Example identifiers are "en_US"
(the default U.S. English keyboard) and "he_IL" (the Hebrew keyboard, which is right-to-left).

(window.UIHelper.setKeyboardInputModeIdentifier):
(window.UIHelper):

Location:
trunk
Files:
3 added
34 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r238935 r238939  
     12018-12-06  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] WKWebView should match UITextView behavior when editing text with an RTL keyboard
     4        https://bugs.webkit.org/show_bug.cgi?id=187554
     5        <rdar://problem/42075638>
     6
     7        Reviewed by Tim Horton.
     8
     9        Add a new layout test to verify that when focusing an editable WKWebView using a right-to-left keyboard input
     10        mode, we will set the base writing direction to be right-to-left, and vice versa.
     11
     12        * TestExpectations:
     13        * editing/input/ios/rtl-keyboard-input-on-focus-expected.txt: Added.
     14        * editing/input/ios/rtl-keyboard-input-on-focus.html: Added.
     15        * platform/ios-wk2/TestExpectations:
     16        * resources/ui-helper.js:
     17
     18        Add a UIHelper method to set the keyboard input mode to the given identifier. Example identifiers are "en_US"
     19        (the default U.S. English keyboard) and "he_IL" (the Hebrew keyboard, which is right-to-left).
     20
     21        (window.UIHelper.setKeyboardInputModeIdentifier):
     22        (window.UIHelper):
     23
    1242018-12-06  Jiewen Tan  <jiewen_tan@apple.com>
    225
  • trunk/LayoutTests/TestExpectations

    r238907 r238939  
    1616editing/mac [ Skip ]
    1717editing/caret/ios [ Skip ]
     18editing/input/ios [ Skip ]
    1819editing/find [ Skip ]
    1920editing/pasteboard/gtk [ Skip ]
  • trunk/LayoutTests/platform/ios-wk2/TestExpectations

    r238935 r238939  
    1616fast/web-share [ Pass ]
    1717editing/find [ Pass ]
     18editing/input/ios [ Pass ]
    1819
    1920editing/selection/character-granularity-rect.html [ Failure ]
  • trunk/LayoutTests/resources/ui-helper.js

    r238623 r238939  
    477477        return new Promise(resolve => testRunner.runUIScript(`uiController.setMinimumEffectiveWidth(${effectiveWidth})`, resolve));
    478478    }
     479
     480    static setKeyboardInputModeIdentifier(identifier)
     481    {
     482        if (!this.isWebKit2())
     483            return Promise.resolve();
     484
     485        const escapedIdentifier = identifier.replace(/`/g, "\\`");
     486        return new Promise(resolve => testRunner.runUIScript(`uiController.setKeyboardInputModeIdentifier(\`${escapedIdentifier}\`)`, resolve));
     487    }
    479488}
  • trunk/Source/WebKit/ChangeLog

    r238937 r238939  
     12018-12-06  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] WKWebView should match UITextView behavior when editing text with an RTL keyboard
     4        https://bugs.webkit.org/show_bug.cgi?id=187554
     5        <rdar://problem/42075638>
     6
     7        Reviewed by Tim Horton.
     8
     9        Add support for automatically switching the base writing direction to the default writing direction with respect
     10        to the current keyboard in an editable WKWebView by implementing `-setBaseWritingDirection:forRange:`. On iOS 12
     11        and earlier, UIKit invokes this protocol method whenever the keyboard is changed to one with a different writing
     12        direction, although in some other versions of iOS, this only happens when first focusing an editable area.
     13
     14        Test: editing/input/ios/rtl-keyboard-input-on-focus.html
     15
     16        * Platform/spi/ios/UIKitSPI.h:
     17
     18        Declare UIKeyboardImpl IPI methods mostly for use in WebKitTestRunner (with the exception of
     19        `-setInitialDirection`, which we may invoke when we receive the first post-layout EditorState update after
     20        focusing an editable element).
     21
     22        * UIProcess/PageClient.h:
     23        * UIProcess/WebPageProxy.cpp:
     24        (WebKit::WebPageProxy::increaseListLevel):
     25        (WebKit::WebPageProxy::decreaseListLevel):
     26        (WebKit::WebPageProxy::changeListType):
     27        (WebKit::WebPageProxy::setBaseWritingDirection):
     28
     29        Drive-by style fixes: make these bail and return early if `!isValid()`.
     30
     31        (WebKit::WebPageProxy::resetStateAfterProcessExited):
     32
     33        Reset assisted node state in the UI process upon web process termination.
     34
     35        * UIProcess/WebPageProxy.h:
     36
     37        Add plumbing for `setBaseWritingDirection`, from `WebPageProxy` to `WebPage` to `Editor`.
     38
     39        * UIProcess/ios/PageClientImplIOS.h:
     40        * UIProcess/ios/PageClientImplIOS.mm:
     41        (WebKit::PageClientImpl::didReceiveEditorStateUpdateAfterFocus):
     42        * UIProcess/ios/WKContentViewInteraction.h:
     43        * UIProcess/ios/WKContentViewInteraction.mm:
     44        (-[WKContentView baseWritingDirectionForPosition:inDirection:]):
     45        (coreWritingDirection):
     46        (-[WKContentView setBaseWritingDirection:forRange:]):
     47
     48        Support `-setBaseWritingDirectionForPosition:forRange:`, but only in the case where the given range is the
     49        selected range. This is all that's currently needed to fulfill the requirements in <rdar://problem/42075638>,
     50        though we could potentially add full support for this in the future by mapping the given text range to a DOM
     51        range and moving the selection prior to setting the base writing direction.
     52
     53        (-[WKContentView _didReceiveEditorStateUpdateAfterFocus]):
     54
     55        Add a hook to notify WKContentView when the first post-layout EditorState has been received in the UI process.
     56        When this is invoked, if the web view is editable and the selection is not a range, we call into `UIKeyboardImpl`
     57        to change the initial writing direction if necessary.
     58
     59        * UIProcess/ios/WebPageProxyIOS.mm:
     60        (WebKit::WebPageProxy::startAssistingNode):
     61        (WebKit::WebPageProxy::stopAssistingNode):
     62        (WebKit::WebPageProxy::editorStateChanged):
     63        * WebProcess/WebPage/WebPage.cpp:
     64        (WebKit::WebPage::setBaseWritingDirection):
     65        * WebProcess/WebPage/WebPage.h:
     66        * WebProcess/WebPage/WebPage.messages.in:
     67
    1682018-12-06  David Quesada  <david_quesada@apple.com>
    269
  • trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h

    r238697 r238939  
    914914
    915915@interface UIKeyboardInputMode : UITextInputMode <NSCopying>
     916+ (UIKeyboardInputMode *)keyboardInputModeWithIdentifier:(NSString *)identifier;
    916917@property (nonatomic, readonly, retain) NSArray <NSString *> *multilingualLanguages;
    917918@property (nonatomic, readonly, retain) NSString *languageWithRegion;
     
    10631064@end
    10641065
     1066@interface UIKeyboardImpl (IPI)
     1067- (void)setInitialDirection;
     1068- (void)prepareKeyboardInputModeFromPreferences:(UIKeyboardInputMode *)lastUsedMode;
     1069@property (nonatomic, readonly) UIKeyboardInputMode *currentInputModeInPreference;
     1070@end
     1071
    10651072@interface _UILayerHostView : UIView
    10661073@end
  • trunk/Source/WebKit/UIProcess/PageClient.h

    r238771 r238939  
    364364    virtual void startAssistingNode(const AssistedNodeInformation&, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, API::Object* userData) = 0;
    365365    virtual void stopAssistingNode() = 0;
     366    virtual void didReceiveEditorStateUpdateAfterFocus() = 0;
    366367    virtual bool isAssistingNode() = 0;
    367368    virtual bool interpretKeyEvent(const NativeWebKeyboardEvent&, bool isCharEvent) = 0;
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r238911 r238939  
    161161#include <WebCore/ValidationBubble.h>
    162162#include <WebCore/WindowFeatures.h>
     163#include <WebCore/WritingDirection.h>
    163164#include <stdio.h>
    164165#include <wtf/NeverDestroyed.h>
     
    18551856void WebPageProxy::increaseListLevel()
    18561857{
    1857     if (isValid())
    1858         m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
     1858    if (!isValid())
     1859        return;
     1860
     1861    m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
    18591862}
    18601863
    18611864void WebPageProxy::decreaseListLevel()
    18621865{
    1863     if (isValid())
    1864         m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
     1866    if (!isValid())
     1867        return;
     1868
     1869    m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
    18651870}
    18661871
    18671872void WebPageProxy::changeListType()
    18681873{
    1869     if (isValid())
    1870         m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
     1874    if (!isValid())
     1875        return;
     1876
     1877    m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
     1878}
     1879
     1880void WebPageProxy::setBaseWritingDirection(WritingDirection direction)
     1881{
     1882    if (!isValid())
     1883        return;
     1884
     1885    m_process->send(Messages::WebPage::SetBaseWritingDirection(direction), m_pageID);
    18711886}
    18721887
     
    64246439
    64256440#if PLATFORM(IOS_FAMILY)
     6441    m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
     6442    m_deferredNodeAssistanceArguments = nullptr;
    64266443    m_activityToken = nullptr;
    64276444#endif
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r238826 r238939  
    179179enum class ShouldSample : bool;
    180180enum class ShouldTreatAsContinuingLoad : bool;
     181enum class WritingDirection : uint8_t;
    181182
    182183struct ApplicationManifest;
     
    563564    void decreaseListLevel();
    564565    void changeListType();
     566
     567    void setBaseWritingDirection(WebCore::WritingDirection);
    565568
    566569    std::optional<WebCore::FontAttributes> cachedFontAttributesAtSelectionStart() const { return m_cachedFontAttributesAtSelectionStart; }
     
    17661769    void startAssistingNode(const AssistedNodeInformation&, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, const UserData&);
    17671770    void stopAssistingNode();
     1771    void didReceiveEditorStateUpdateAfterFocus();
    17681772
    17691773    void showInspectorHighlight(const WebCore::Highlight&);
     
    22532257#if PLATFORM(IOS_FAMILY)
    22542258    std::unique_ptr<NodeAssistanceArguments> m_deferredNodeAssistanceArguments;
     2259    bool m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement { false };
    22552260    bool m_forceAlwaysUserScalable { false };
    22562261    WebCore::FloatSize m_viewportConfigurationViewLayoutSize;
  • trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h

    r238771 r238939  
    141141    void startAssistingNode(const AssistedNodeInformation&, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, API::Object* userData) override;
    142142    void stopAssistingNode() override;
     143    void didReceiveEditorStateUpdateAfterFocus() override;
    143144    bool isAssistingNode() override;
    144145    void selectionDidChange() override;
  • trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm

    r238771 r238939  
    579579}
    580580
     581void PageClientImpl::didReceiveEditorStateUpdateAfterFocus()
     582{
     583    [m_contentView _didReceiveEditorStateUpdateAfterFocus];
     584}
     585
    581586void PageClientImpl::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect, WebCore::RouteSharingPolicy policy, const String& contextUID)
    582587{
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h

    r238697 r238939  
    389389- (void)_startAssistingNode:(const WebKit::AssistedNodeInformation&)information userIsInteracting:(BOOL)userIsInteracting blurPreviousNode:(BOOL)blurPreviousNode changingActivityState:(BOOL)changingActivityState userObject:(NSObject <NSSecureCoding> *)userObject;
    390390- (void)_stopAssistingNode;
     391- (void)_didReceiveEditorStateUpdateAfterFocus;
    391392- (void)_selectionChanged;
    392393- (void)_updateChangedSelection;
  • trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

    r238814 r238939  
    9393#import <WebCore/VisibleSelection.h>
    9494#import <WebCore/WebEvent.h>
     95#import <WebCore/WritingDirection.h>
    9596#import <WebKit/WebSelectionRect.h> // FIXME: WK2 should not include WebKit headers!
    9697#import <pal/spi/cg/CoreGraphicsSPI.h>
     
    35833584}
    35843585
    3585 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
    3586 - (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
    3587 {
    3588     return UITextWritingDirectionLeftToRight;
    3589 }
    3590 
    3591 - (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range
    3592 {
    3593 }
    3594 ALLOW_DEPRECATED_DECLARATIONS_END
     3586- (NSWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
     3587{
     3588    return NSWritingDirectionLeftToRight;
     3589}
     3590
     3591static WritingDirection coreWritingDirection(NSWritingDirection direction)
     3592{
     3593    switch (direction) {
     3594    case NSWritingDirectionNatural:
     3595        return WritingDirection::Natural;
     3596    case NSWritingDirectionLeftToRight:
     3597        return WritingDirection::LeftToRight;
     3598    case NSWritingDirectionRightToLeft:
     3599        return WritingDirection::RightToLeft;
     3600    default:
     3601        ASSERT_NOT_REACHED();
     3602        return WritingDirection::Natural;
     3603    }
     3604}
     3605
     3606- (void)setBaseWritingDirection:(NSWritingDirection)direction forRange:(UITextRange *)range
     3607{
     3608    if (range && ![range isEqual:self.selectedTextRange]) {
     3609        // We currently only support changing the base writing direction at the selection.
     3610        return;
     3611    }
     3612    _page->setBaseWritingDirection(coreWritingDirection(direction));
     3613}
    35953614
    35963615- (CGRect)firstRectForRange:(UITextRange *)range
     
    45144533}
    45154534
     4535- (void)_didReceiveEditorStateUpdateAfterFocus
     4536{
     4537    if (!_page->isEditable())
     4538        return;
     4539
     4540    auto& editorState = _page->editorState();
     4541    if (editorState.selectionIsNone || editorState.selectionIsRange)
     4542        return;
     4543
     4544    UIKeyboardImpl *keyboard = UIKeyboardImpl.activeInstance;
     4545    if (keyboard.delegate != self)
     4546        return;
     4547
     4548    // Synchronize the keyboard's writing direction with the newly received EditorState.
     4549    [keyboard setInitialDirection];
     4550}
     4551
    45164552- (void)updateCurrentAssistedNodeInformation:(Function<void(bool didUpdate)>&&)callback
    45174553{
  • trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm

    r238697 r238939  
    896896void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, const UserData& userData)
    897897{
     898    m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = true;
     899
    898900    API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
    899901    if (m_editorState.isMissingPostLayoutData) {
     
    907909void WebPageProxy::stopAssistingNode()
    908910{
     911    m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
    909912    m_deferredNodeAssistanceArguments = nullptr;
    910913    pageClient().stopAssistingNode();
     
    10551058   
    10561059    m_editorState = editorState;
     1060
     1061    if (m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement && !m_editorState.isMissingPostLayoutData) {
     1062        pageClient().didReceiveEditorStateUpdateAfterFocus();
     1063        m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
     1064    }
    10571065   
    10581066    // Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r238857 r238939  
    220220#include <WebCore/VisibleUnits.h>
    221221#include <WebCore/WebGLStateTracker.h>
     222#include <WebCore/WritingDirection.h>
    222223#include <WebCore/markup.h>
    223224#include <pal/SessionID.h>
     
    11651166}
    11661167
     1168void WebPage::setBaseWritingDirection(WritingDirection direction)
     1169{
     1170    m_page->focusController().focusedOrMainFrame().editor().setBaseWritingDirection(direction);
     1171}
     1172
    11671173bool WebPage::isEditingCommandEnabled(const String& commandName)
    11681174{
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r238771 r238939  
    170170enum class ShouldTreatAsContinuingLoad : bool;
    171171enum class TextIndicatorPresentationTransition : uint8_t;
     172enum class WritingDirection : uint8_t;
    172173
    173174struct BackForwardItemIdentifier;
     
    12161217    void changeListType();
    12171218
     1219    void setBaseWritingDirection(WebCore::WritingDirection);
     1220
    12181221    void setNeedsFontAttributes(bool);
    12191222
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in

    r238771 r238939  
    223223    ChangeListType()
    224224
     225    SetBaseWritingDirection(enum:uint8_t WebCore::WritingDirection direction)
     226
    225227    SetNeedsFontAttributes(bool needsFontAttributes)
    226228
  • trunk/Tools/ChangeLog

    r238921 r238939  
     12018-12-06  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [iOS] WKWebView should match UITextView behavior when editing text with an RTL keyboard
     4        https://bugs.webkit.org/show_bug.cgi?id=187554
     5        <rdar://problem/42075638>
     6
     7        Reviewed by Tim Horton.
     8
     9        Add support for simulating the keyboard input mode in layout tests using UIScriptController, as well as a new
     10        `TestOption` to make the web view editable.
     11
     12        * DumpRenderTree/ios/UIScriptControllerIOS.mm:
     13        (WTR::UIScriptController::setKeyboardInputModeIdentifier):
     14        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
     15        * TestRunnerShared/UIScriptContext/UIScriptController.cpp:
     16        (WTR::UIScriptController::setKeyboardInputModeIdentifier):
     17        * TestRunnerShared/UIScriptContext/UIScriptController.h:
     18        * WebKitTestRunner/PlatformWebView.h:
     19        * WebKitTestRunner/TestController.cpp:
     20        (WTR::updateTestOptionsFromTestHeader):
     21        * WebKitTestRunner/TestController.h:
     22        (WTR::TestController::overriddenKeyboardInputMode const):
     23        * WebKitTestRunner/TestOptions.h:
     24        (WTR::TestOptions::hasSameInitializationOptions const):
     25        * WebKitTestRunner/cocoa/TestControllerCocoa.mm:
     26        (WTR::TestController::platformCreateWebView):
     27        * WebKitTestRunner/gtk/PlatformWebViewGtk.cpp:
     28        (WTR::PlatformWebView::setEditable):
     29        * WebKitTestRunner/ios/PlatformWebViewIOS.mm:
     30        (WTR::PlatformWebView::setEditable):
     31        * WebKitTestRunner/ios/TestControllerIOS.mm:
     32        (WTR::TestController::platformResetStateToConsistentValues):
     33        (WTR::swizzleCurrentInputMode):
     34        (WTR::TestController::setKeyboardInputModeIdentifier):
     35
     36        Swizzle out several `UIKeyboardInputModeController` methods in order to convince UIKit that the user has
     37        selected a `UIKeyboardInputMode` corresponding to the given identifier. The call to
     38        `-prepareKeyboardInputModeFromPreferences:` is also necessary on iOS 12 in order to update cached writing
     39        direction state in UIKit.
     40
     41        * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
     42        (WTR::UIScriptController::setKeyboardInputModeIdentifier):
     43        * WebKitTestRunner/mac/PlatformWebViewMac.mm:
     44        (WTR::PlatformWebView::setEditable):
     45        * WebKitTestRunner/win/PlatformWebViewWin.cpp:
     46        (WTR::PlatformWebView::setEditable):
     47        * WebKitTestRunner/wpe/PlatformWebViewWPE.cpp:
     48        (WTR::PlatformWebView::setEditable):
     49
    1502018-12-05  Wenson Hsieh  <wenson_hsieh@apple.com>
    251
  • trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm

    r238623 r238939  
    437437}
    438438
     439void UIScriptController::setKeyboardInputModeIdentifier(JSStringRef)
     440{
     441}
     442
    439443}
    440444
  • trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl

    r238623 r238939  
    259259    readonly attribute object inputViewBounds;
    260260
     261    void setKeyboardInputModeIdentifier(DOMString identifier);
     262
    261263    void replaceTextAtRange(DOMString text, long location, long length);
    262264    void removeAllDynamicDictionaries();
  • trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp

    r238623 r238939  
    511511}
    512512
     513void UIScriptController::setKeyboardInputModeIdentifier(JSStringRef)
     514{
     515}
     516
    513517#endif
    514518
  • trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h

    r238623 r238939  
    172172    JSObjectRef inputViewBounds() const;
    173173
     174    void setKeyboardInputModeIdentifier(JSStringRef);
     175
    174176    void replaceTextAtRange(JSStringRef, int location, int length);
    175177    void removeAllDynamicDictionaries();
  • trunk/Tools/WebKitTestRunner/PlatformWebView.h

    r238098 r238939  
    104104    void setDrawsBackground(bool);
    105105
     106    void setEditable(bool);
     107
    106108    void removeFromWindow();
    107109    void addToWindow();
  • trunk/Tools/WebKitTestRunner/TestController.cpp

    r238264 r238939  
    12581258        else if (key == "enableEditableImages")
    12591259            testOptions.enableEditableImages = parseBooleanTestHeaderValue(value);
     1260        else if (key == "editable")
     1261            testOptions.editable = parseBooleanTestHeaderValue(value);
    12601262        pairStart = pairEnd + 1;
    12611263    }
  • trunk/Tools/WebKitTestRunner/TestController.h

    r238921 r238939  
    4141#if PLATFORM(COCOA)
    4242#include "ClassMethodSwizzler.h"
     43#include "InstanceMethodSwizzler.h"
    4344#endif
    4445
    4546OBJC_CLASS NSString;
     47OBJC_CLASS UIKeyboardInputMode;
    4648OBJC_CLASS WKWebViewConfiguration;
    4749
     
    271273    void setDefaultCalendarType(NSString *identifier);
    272274#endif // PLATFORM(COCOA)
     275
     276#if PLATFORM(IOS_FAMILY)
     277    void setKeyboardInputModeIdentifier(const String&);
     278    UIKeyboardInputMode *overriddenKeyboardInputMode() const { return m_overriddenKeyboardInputMode.get(); }
     279#endif
     280
    273281private:
    274282    WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(WKContextConfigurationRef);
     
    442450    WKRetainPtr<WKPageGroupRef> m_pageGroup;
    443451
     452#if PLATFORM(IOS_FAMILY)
     453    Vector<std::unique_ptr<InstanceMethodSwizzler>> m_inputModeSwizzlers;
     454    RetainPtr<UIKeyboardInputMode> m_overriddenKeyboardInputMode;
     455#endif
     456
    444457    enum State {
    445458        Initial,
  • trunk/Tools/WebKitTestRunner/TestOptions.h

    r238108 r238939  
    6666    bool shouldShowSpellCheckingDots { false };
    6767    bool enableEditableImages { false };
     68    bool editable { false };
    6869
    6970    float deviceScaleFactor { 1 };
     
    108109            || shouldShowSpellCheckingDots != options.shouldShowSpellCheckingDots
    109110            || shouldIgnoreMetaViewport != options.shouldIgnoreMetaViewport
    110             || enableEditableImages != options.enableEditableImages)
     111            || enableEditableImages != options.enableEditableImages
     112            || editable != options.editable)
    111113            return false;
    112114
  • trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm

    r238921 r238939  
    172172    if (options.punchOutWhiteBackgroundsInDarkMode)
    173173        m_mainWebView->setDrawsBackground(false);
     174
     175    if (options.editable)
     176        m_mainWebView->setEditable(true);
    174177#else
    175178    m_mainWebView = std::make_unique<PlatformWebView>(globalWebViewConfiguration, options);
  • trunk/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp

    r233869 r238939  
    199199}
    200200
     201void PlatformWebView::setEditable(bool)
     202{
     203}
     204
    201205} // namespace WTR
    202206
  • trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm

    r238635 r238939  
    295295}
    296296
     297void PlatformWebView::setEditable(bool editable)
     298{
     299#if WK_API_ENABLED
     300    m_view._editable = editable;
     301#else
     302    UNUSED_PARAM(editable);
     303#endif
     304}
     305
    297306bool PlatformWebView::drawsBackground() const
    298307{
  • trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm

    r238134 r238939  
    117117
    118118    [[UIDevice currentDevice] setOrientation:UIDeviceOrientationPortrait animated:NO];
     119
     120    m_inputModeSwizzlers.clear();
     121    m_overriddenKeyboardInputMode = nil;
    119122   
    120123    BOOL shouldRestoreFirstResponder = NO;
     
    199202}
    200203
     204static UIKeyboardInputMode *swizzleCurrentInputMode()
     205{
     206    return TestController::singleton().overriddenKeyboardInputMode();
     207}
     208
     209static NSArray<UIKeyboardInputMode *> *swizzleActiveInputModes()
     210{
     211    return @[ TestController::singleton().overriddenKeyboardInputMode() ];
     212}
     213
     214void TestController::setKeyboardInputModeIdentifier(const String& identifier)
     215{
     216    m_inputModeSwizzlers.clear();
     217    m_overriddenKeyboardInputMode = [UIKeyboardInputMode keyboardInputModeWithIdentifier:identifier];
     218    if (!m_overriddenKeyboardInputMode) {
     219        ASSERT_NOT_REACHED();
     220        return;
     221    }
     222
     223    auto controllerClass = UIKeyboardInputModeController.class;
     224    m_inputModeSwizzlers.reserveCapacity(3);
     225    m_inputModeSwizzlers.uncheckedAppend(std::make_unique<InstanceMethodSwizzler>(controllerClass, @selector(currentInputMode), reinterpret_cast<IMP>(swizzleCurrentInputMode)));
     226    m_inputModeSwizzlers.uncheckedAppend(std::make_unique<InstanceMethodSwizzler>(controllerClass, @selector(currentInputModeInPreference), reinterpret_cast<IMP>(swizzleCurrentInputMode)));
     227    m_inputModeSwizzlers.uncheckedAppend(std::make_unique<InstanceMethodSwizzler>(controllerClass, @selector(activeInputModes), reinterpret_cast<IMP>(swizzleActiveInputModes)));
     228    [UIKeyboardImpl.sharedInstance prepareKeyboardInputModeFromPreferences:nil];
     229}
     230
    201231} // namespace WTR
  • trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm

    r238538 r238939  
    926926}
    927927
     928void UIScriptController::setKeyboardInputModeIdentifier(JSStringRef identifier)
     929{
     930    TestController::singleton().setKeyboardInputModeIdentifier(toWTFString(toWK(identifier)));
     931}
     932
    928933void UIScriptController::toggleCapsLock(JSValueRef callback)
    929934{
  • trunk/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm

    r235837 r238939  
    213213}
    214214
     215void PlatformWebView::setEditable(bool editable)
     216{
     217#if WK_API_ENABLED
     218    m_view._editable = editable;
     219#else
     220    UNUSED_PARAM(editable);
     221#endif
     222}
     223
    215224RetainPtr<CGImageRef> PlatformWebView::windowSnapshotImage()
    216225{
  • trunk/Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp

    r238296 r238939  
    260260}
    261261
     262void PlatformWebView::setEditable(bool)
     263{
     264}
     265
    262266} // namespace WTR
  • trunk/Tools/WebKitTestRunner/wpe/PlatformWebViewWPE.cpp

    r233869 r238939  
    142142}
    143143
     144void PlatformWebView::setEditable(bool)
     145{
     146}
     147
    144148} // namespace WTR
Note: See TracChangeset for help on using the changeset viewer.