Diff
Modified: trunk/LayoutTests/ChangeLog (238938 => 238939)
--- trunk/LayoutTests/ChangeLog 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/LayoutTests/ChangeLog 2018-12-06 21:22:19 UTC (rev 238939)
@@ -1,3 +1,26 @@
+2018-12-06 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [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.
+
+ 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):
+
2018-12-06 Jiewen Tan <jiewen_...@apple.com>
Layout Test http/tests/misc/resource-timing-resolution.html is a flaky failure
Modified: trunk/LayoutTests/TestExpectations (238938 => 238939)
--- trunk/LayoutTests/TestExpectations 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/LayoutTests/TestExpectations 2018-12-06 21:22:19 UTC (rev 238939)
@@ -15,6 +15,7 @@
displaylists [ Skip ]
editing/mac [ Skip ]
editing/caret/ios [ Skip ]
+editing/input/ios [ Skip ]
editing/find [ Skip ]
editing/pasteboard/gtk [ Skip ]
editing/selection/ios [ Skip ]
Added: trunk/LayoutTests/editing/input/ios/rtl-keyboard-input-on-focus-expected.txt (0 => 238939)
--- trunk/LayoutTests/editing/input/ios/rtl-keyboard-input-on-focus-expected.txt (rev 0)
+++ trunk/LayoutTests/editing/input/ios/rtl-keyboard-input-on-focus-expected.txt 2018-12-06 21:22:19 UTC (rev 238939)
@@ -0,0 +1,38 @@
+
+
+Using Hebrew keyboard:
+ <div><br></div>
+ <div style="direction: rtl;"><br></div>
+
+
+
+Using English keyboard:
+ <div><br></div>
+ <div style="direction: ltr;"><br></div>
+
+
+
+Observed 'beforeinput' events: [
+ {
+ "inputType": "formatSetInlineTextDirection",
+ "data": "rtl",
+ "order": 1
+ },
+ {
+ "inputType": "formatSetInlineTextDirection",
+ "data": "ltr",
+ "order": 3
+ }
+]
+Observed 'input' events: [
+ {
+ "inputType": "formatSetInlineTextDirection",
+ "data": "rtl",
+ "order": 2
+ },
+ {
+ "inputType": "formatSetInlineTextDirection",
+ "data": "ltr",
+ "order": 4
+ }
+]
Added: trunk/LayoutTests/editing/input/ios/rtl-keyboard-input-on-focus.html (0 => 238939)
--- trunk/LayoutTests/editing/input/ios/rtl-keyboard-input-on-focus.html (rev 0)
+++ trunk/LayoutTests/editing/input/ios/rtl-keyboard-input-on-focus.html 2018-12-06 21:22:19 UTC (rev 238939)
@@ -0,0 +1,79 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true, editable=true ] -->
+<html>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+<head>
+ <script src=""
+ <script src=""
+ <style>
+ body {
+ margin: 0;
+ }
+ </style>
+ <script>
+ function appendOutput(string) {
+ let pre = document.createElement("pre");
+ pre.textContent = string;
+ document.body.appendChild(pre);
+ }
+
+ beforeInputEvents = [];
+ inputEvents = [];
+ eventNumber = 0;
+
+ async function run()
+ {
+ script.remove();
+
+ document.body.addEventListener("beforeinput", event => {
+ beforeInputEvents.push({
+ "inputType": event.inputType,
+ "data": event.data,
+ "order": ++eventNumber
+ });
+ });
+
+ document.body.addEventListener("input", event => {
+ inputEvents.push({
+ "inputType": event.inputType,
+ "data": event.data,
+ "order": ++eventNumber
+ });
+ });
+
+ await UIHelper.setKeyboardInputModeIdentifier("he_IL");
+ await UIHelper.activateAndWaitForInputSessionAt(100, 250);
+ await UIHelper.ensurePresentationUpdate();
+ const markupUsingHebrewKeyboard = document.body.innerHTML;
+
+ document.body.blur();
+ await UIHelper.waitForKeyboardToHide();
+ await UIHelper.setKeyboardInputModeIdentifier("en_US");
+ await UIHelper.activateAndWaitForInputSessionAt(100, 250);
+ await UIHelper.ensurePresentationUpdate();
+ const markupUsingEnglishKeyboard = document.body.innerHTML;
+
+ appendOutput(`Using Hebrew keyboard: ${markupUsingHebrewKeyboard}`);
+ appendOutput(`Using English keyboard: ${markupUsingEnglishKeyboard}`);
+ appendOutput(`Observed 'beforeinput' events: ${JSON.stringify(beforeInputEvents, null, 4)}`);
+ appendOutput(`Observed 'input' events: ${JSON.stringify(inputEvents, null, 4)}`);
+ testRunner.notifyDone();
+ }
+ </script>
+</head>
+<body _onload_="run()">
+ <div><br></div>
+ <div><br></div>
+</body>
+<script id="script">
+if (window.testRunner) {
+ testRunner.waitUntilDone();
+ testRunner.dumpAsText();
+} else {
+ const description = document.createElement("p");
+ description.textContent = "Verifies that focusing an editable area with an RTL keyboard switches text direction to RTL. "
+ + "To test manually, switch to a Hebrew keyboard and focus the editable area. "
+ + "The editable area should be made RTL.";
+ document.body.prepend(description);
+}
+</script>
+</html>
Modified: trunk/LayoutTests/platform/ios-wk2/TestExpectations (238938 => 238939)
--- trunk/LayoutTests/platform/ios-wk2/TestExpectations 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/LayoutTests/platform/ios-wk2/TestExpectations 2018-12-06 21:22:19 UTC (rev 238939)
@@ -15,6 +15,7 @@
tiled-drawing/ios [ Pass ]
fast/web-share [ Pass ]
editing/find [ Pass ]
+editing/input/ios [ Pass ]
editing/selection/character-granularity-rect.html [ Failure ]
Modified: trunk/LayoutTests/resources/ui-helper.js (238938 => 238939)
--- trunk/LayoutTests/resources/ui-helper.js 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/LayoutTests/resources/ui-helper.js 2018-12-06 21:22:19 UTC (rev 238939)
@@ -476,4 +476,13 @@
return new Promise(resolve => testRunner.runUIScript(`uiController.setMinimumEffectiveWidth(${effectiveWidth})`, resolve));
}
+
+ static setKeyboardInputModeIdentifier(identifier)
+ {
+ if (!this.isWebKit2())
+ return Promise.resolve();
+
+ const escapedIdentifier = identifier.replace(/`/g, "\\`");
+ return new Promise(resolve => testRunner.runUIScript(`uiController.setKeyboardInputModeIdentifier(\`${escapedIdentifier}\`)`, resolve));
+ }
}
Modified: trunk/Source/WebKit/ChangeLog (238938 => 238939)
--- trunk/Source/WebKit/ChangeLog 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/ChangeLog 2018-12-06 21:22:19 UTC (rev 238939)
@@ -1,3 +1,70 @@
+2018-12-06 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [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.
+
+ 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:
+
2018-12-06 David Quesada <david_ques...@apple.com>
-[WKProcessPool _resumeDownloadFromData:path:] should allow specifying the originating web view
Modified: trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h (238938 => 238939)
--- trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -913,6 +913,7 @@
@end
@interface UIKeyboardInputMode : UITextInputMode <NSCopying>
++ (UIKeyboardInputMode *)keyboardInputModeWithIdentifier:(NSString *)identifier;
@property (nonatomic, readonly, retain) NSArray <NSString *> *multilingualLanguages;
@property (nonatomic, readonly, retain) NSString *languageWithRegion;
@end
@@ -1062,6 +1063,12 @@
- (CGFloat)getVerticalOverlapForView:(UIView *)view usingKeyboardInfo:(NSDictionary *)info;
@end
+@interface UIKeyboardImpl (IPI)
+- (void)setInitialDirection;
+- (void)prepareKeyboardInputModeFromPreferences:(UIKeyboardInputMode *)lastUsedMode;
+@property (nonatomic, readonly) UIKeyboardInputMode *currentInputModeInPreference;
+@end
+
@interface _UILayerHostView : UIView
@end
Modified: trunk/Source/WebKit/UIProcess/PageClient.h (238938 => 238939)
--- trunk/Source/WebKit/UIProcess/PageClient.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/UIProcess/PageClient.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -363,6 +363,7 @@
virtual void startAssistingNode(const AssistedNodeInformation&, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, API::Object* userData) = 0;
virtual void stopAssistingNode() = 0;
+ virtual void didReceiveEditorStateUpdateAfterFocus() = 0;
virtual bool isAssistingNode() = 0;
virtual bool interpretKeyEvent(const NativeWebKeyboardEvent&, bool isCharEvent) = 0;
virtual void positionInformationDidChange(const InteractionInformationAtPosition&) = 0;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (238938 => 238939)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2018-12-06 21:22:19 UTC (rev 238939)
@@ -160,6 +160,7 @@
#include <WebCore/TextIndicator.h>
#include <WebCore/ValidationBubble.h>
#include <WebCore/WindowFeatures.h>
+#include <WebCore/WritingDirection.h>
#include <stdio.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/SystemTracing.h>
@@ -1854,22 +1855,36 @@
void WebPageProxy::increaseListLevel()
{
- if (isValid())
- m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
+ if (!isValid())
+ return;
+
+ m_process->send(Messages::WebPage::IncreaseListLevel(), m_pageID);
}
void WebPageProxy::decreaseListLevel()
{
- if (isValid())
- m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
+ if (!isValid())
+ return;
+
+ m_process->send(Messages::WebPage::DecreaseListLevel(), m_pageID);
}
void WebPageProxy::changeListType()
{
- if (isValid())
- m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
+ if (!isValid())
+ return;
+
+ m_process->send(Messages::WebPage::ChangeListType(), m_pageID);
}
+void WebPageProxy::setBaseWritingDirection(WritingDirection direction)
+{
+ if (!isValid())
+ return;
+
+ m_process->send(Messages::WebPage::SetBaseWritingDirection(direction), m_pageID);
+}
+
void WebPageProxy::updateFontAttributesAfterEditorStateChange()
{
m_cachedFontAttributesAtSelectionStart.reset();
@@ -6423,6 +6438,8 @@
#endif
#if PLATFORM(IOS_FAMILY)
+ m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
+ m_deferredNodeAssistanceArguments = nullptr;
m_activityToken = nullptr;
#endif
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.h (238938 => 238939)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -178,6 +178,7 @@
enum class NotificationDirection : uint8_t;
enum class ShouldSample : bool;
enum class ShouldTreatAsContinuingLoad : bool;
+enum class WritingDirection : uint8_t;
struct ApplicationManifest;
struct BackForwardItemIdentifier;
@@ -563,6 +564,8 @@
void decreaseListLevel();
void changeListType();
+ void setBaseWritingDirection(WebCore::WritingDirection);
+
std::optional<WebCore::FontAttributes> cachedFontAttributesAtSelectionStart() const { return m_cachedFontAttributesAtSelectionStart; }
#if PLATFORM(COCOA)
@@ -1765,6 +1768,7 @@
void startAssistingNode(const AssistedNodeInformation&, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, const UserData&);
void stopAssistingNode();
+ void didReceiveEditorStateUpdateAfterFocus();
void showInspectorHighlight(const WebCore::Highlight&);
void hideInspectorHighlight();
@@ -2252,6 +2256,7 @@
#if PLATFORM(IOS_FAMILY)
std::unique_ptr<NodeAssistanceArguments> m_deferredNodeAssistanceArguments;
+ bool m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement { false };
bool m_forceAlwaysUserScalable { false };
WebCore::FloatSize m_viewportConfigurationViewLayoutSize;
double m_viewportConfigurationLayoutSizeScaleFactor { 1 };
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (238938 => 238939)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -140,6 +140,7 @@
void startAssistingNode(const AssistedNodeInformation&, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, API::Object* userData) override;
void stopAssistingNode() override;
+ void didReceiveEditorStateUpdateAfterFocus() override;
bool isAssistingNode() override;
void selectionDidChange() override;
bool interpretKeyEvent(const NativeWebKeyboardEvent&, bool isCharEvent) override;
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (238938 => 238939)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2018-12-06 21:22:19 UTC (rev 238939)
@@ -578,6 +578,11 @@
[m_contentView _stopAssistingNode];
}
+void PageClientImpl::didReceiveEditorStateUpdateAfterFocus()
+{
+ [m_contentView _didReceiveEditorStateUpdateAfterFocus];
+}
+
void PageClientImpl::showPlaybackTargetPicker(bool hasVideo, const IntRect& elementRect, WebCore::RouteSharingPolicy policy, const String& contextUID)
{
[m_contentView _showPlaybackTargetPicker:hasVideo fromRect:elementRect routeSharingPolicy:policy routingContextUID:contextUID];
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (238938 => 238939)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -388,6 +388,7 @@
- (void)_disableDoubleTapGesturesDuringTapIfNecessary:(uint64_t)requestID;
- (void)_startAssistingNode:(const WebKit::AssistedNodeInformation&)information userIsInteracting:(BOOL)userIsInteracting blurPreviousNode:(BOOL)blurPreviousNode changingActivityState:(BOOL)changingActivityState userObject:(NSObject <NSSecureCoding> *)userObject;
- (void)_stopAssistingNode;
+- (void)_didReceiveEditorStateUpdateAfterFocus;
- (void)_selectionChanged;
- (void)_updateChangedSelection;
- (BOOL)_interpretKeyEvent:(::WebEvent *)theEvent isCharEvent:(BOOL)isCharEvent;
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (238938 => 238939)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2018-12-06 21:22:19 UTC (rev 238939)
@@ -92,6 +92,7 @@
#import <WebCore/TextIndicator.h>
#import <WebCore/VisibleSelection.h>
#import <WebCore/WebEvent.h>
+#import <WebCore/WritingDirection.h>
#import <WebKit/WebSelectionRect.h> // FIXME: WK2 should not include WebKit headers!
#import <pal/spi/cg/CoreGraphicsSPI.h>
#import <pal/spi/cocoa/DataDetectorsCoreSPI.h>
@@ -3582,17 +3583,35 @@
return nil;
}
-ALLOW_DEPRECATED_DECLARATIONS_BEGIN
-- (UITextWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
+- (NSWritingDirection)baseWritingDirectionForPosition:(UITextPosition *)position inDirection:(UITextStorageDirection)direction
{
- return UITextWritingDirectionLeftToRight;
+ return NSWritingDirectionLeftToRight;
}
-- (void)setBaseWritingDirection:(UITextWritingDirection)writingDirection forRange:(UITextRange *)range
+static WritingDirection coreWritingDirection(NSWritingDirection direction)
{
+ switch (direction) {
+ case NSWritingDirectionNatural:
+ return WritingDirection::Natural;
+ case NSWritingDirectionLeftToRight:
+ return WritingDirection::LeftToRight;
+ case NSWritingDirectionRightToLeft:
+ return WritingDirection::RightToLeft;
+ default:
+ ASSERT_NOT_REACHED();
+ return WritingDirection::Natural;
+ }
}
-ALLOW_DEPRECATED_DECLARATIONS_END
+- (void)setBaseWritingDirection:(NSWritingDirection)direction forRange:(UITextRange *)range
+{
+ if (range && ![range isEqual:self.selectedTextRange]) {
+ // We currently only support changing the base writing direction at the selection.
+ return;
+ }
+ _page->setBaseWritingDirection(coreWritingDirection(direction));
+}
+
- (CGRect)firstRectForRange:(UITextRange *)range
{
return CGRectZero;
@@ -4513,6 +4532,23 @@
[self _stopSuppressingSelectionAssistantForReason:FocusedElementIsTransparent];
}
+- (void)_didReceiveEditorStateUpdateAfterFocus
+{
+ if (!_page->isEditable())
+ return;
+
+ auto& editorState = _page->editorState();
+ if (editorState.selectionIsNone || editorState.selectionIsRange)
+ return;
+
+ UIKeyboardImpl *keyboard = UIKeyboardImpl.activeInstance;
+ if (keyboard.delegate != self)
+ return;
+
+ // Synchronize the keyboard's writing direction with the newly received EditorState.
+ [keyboard setInitialDirection];
+}
+
- (void)updateCurrentAssistedNodeInformation:(Function<void(bool didUpdate)>&&)callback
{
WeakObjCPtr<WKContentView> weakSelf { self };
Modified: trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm (238938 => 238939)
--- trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/UIProcess/ios/WebPageProxyIOS.mm 2018-12-06 21:22:19 UTC (rev 238939)
@@ -895,6 +895,8 @@
void WebPageProxy::startAssistingNode(const AssistedNodeInformation& information, bool userIsInteracting, bool blurPreviousNode, bool changingActivityState, const UserData& userData)
{
+ m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = true;
+
API::Object* userDataObject = process().transformHandlesToObjects(userData.object()).get();
if (m_editorState.isMissingPostLayoutData) {
m_deferredNodeAssistanceArguments = std::make_unique<NodeAssistanceArguments>(NodeAssistanceArguments { information, userIsInteracting, blurPreviousNode, changingActivityState, userDataObject });
@@ -906,6 +908,7 @@
void WebPageProxy::stopAssistingNode()
{
+ m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
m_deferredNodeAssistanceArguments = nullptr;
pageClient().stopAssistingNode();
}
@@ -1054,6 +1057,11 @@
bool couldChangeSecureInputState = m_editorState.isInPasswordField != editorState.isInPasswordField || m_editorState.selectionIsNone;
m_editorState = editorState;
+
+ if (m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement && !m_editorState.isMissingPostLayoutData) {
+ pageClient().didReceiveEditorStateUpdateAfterFocus();
+ m_waitingForPostLayoutEditorStateUpdateAfterFocusingElement = false;
+ }
// Selection being none is a temporary state when editing. Flipping secure input state too quickly was causing trouble (not fully understood).
if (couldChangeSecureInputState && !editorState.selectionIsNone)
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (238938 => 238939)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp 2018-12-06 21:22:19 UTC (rev 238939)
@@ -219,6 +219,7 @@
#include <WebCore/VisiblePosition.h>
#include <WebCore/VisibleUnits.h>
#include <WebCore/WebGLStateTracker.h>
+#include <WebCore/WritingDirection.h>
#include <WebCore/markup.h>
#include <pal/SessionID.h>
#include <wtf/ProcessID.h>
@@ -1164,6 +1165,11 @@
m_page->focusController().focusedOrMainFrame().editor().changeSelectionListType();
}
+void WebPage::setBaseWritingDirection(WritingDirection direction)
+{
+ m_page->focusController().focusedOrMainFrame().editor().setBaseWritingDirection(direction);
+}
+
bool WebPage::isEditingCommandEnabled(const String& commandName)
{
Frame& frame = m_page->focusController().focusedOrMainFrame();
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (238938 => 238939)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -169,6 +169,7 @@
enum SyntheticClickType : int8_t;
enum class ShouldTreatAsContinuingLoad : bool;
enum class TextIndicatorPresentationTransition : uint8_t;
+enum class WritingDirection : uint8_t;
struct BackForwardItemIdentifier;
struct CompositionUnderline;
@@ -1215,6 +1216,8 @@
void decreaseListLevel();
void changeListType();
+ void setBaseWritingDirection(WebCore::WritingDirection);
+
void setNeedsFontAttributes(bool);
void mouseEvent(const WebMouseEvent&);
Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (238938 => 238939)
--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in 2018-12-06 21:22:19 UTC (rev 238939)
@@ -222,6 +222,8 @@
DecreaseListLevel()
ChangeListType()
+ SetBaseWritingDirection(enum:uint8_t WebCore::WritingDirection direction)
+
SetNeedsFontAttributes(bool needsFontAttributes)
RequestFontAttributesAtSelectionStart(WebKit::CallbackID callbackID)
Modified: trunk/Tools/ChangeLog (238938 => 238939)
--- trunk/Tools/ChangeLog 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/ChangeLog 2018-12-06 21:22:19 UTC (rev 238939)
@@ -1,3 +1,52 @@
+2018-12-06 Wenson Hsieh <wenson_hs...@apple.com>
+
+ [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.
+
+ 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):
+
2018-12-05 Wenson Hsieh <wenson_hs...@apple.com>
[Cocoa] Share ClassMethodSwizzler and InstanceMethodSwizzler between TestWebKitAPI and WebKitTestRunner
Modified: trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm (238938 => 238939)
--- trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm 2018-12-06 21:22:19 UTC (rev 238939)
@@ -436,6 +436,10 @@
return nullptr;
}
+void UIScriptController::setKeyboardInputModeIdentifier(JSStringRef)
+{
}
+}
+
#endif // PLATFORM(IOS_FAMILY)
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl (238938 => 238939)
--- trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2018-12-06 21:22:19 UTC (rev 238939)
@@ -258,6 +258,8 @@
void setDefaultCalendarType(DOMString calendarIdentifier);
readonly attribute object inputViewBounds;
+ void setKeyboardInputModeIdentifier(DOMString identifier);
+
void replaceTextAtRange(DOMString text, long location, long length);
void removeAllDynamicDictionaries();
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp (238938 => 238939)
--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp 2018-12-06 21:22:19 UTC (rev 238939)
@@ -510,6 +510,10 @@
return nullptr;
}
+void UIScriptController::setKeyboardInputModeIdentifier(JSStringRef)
+{
+}
+
#endif
#if !PLATFORM(COCOA)
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h (238938 => 238939)
--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -171,6 +171,8 @@
void setDefaultCalendarType(JSStringRef calendarIdentifier);
JSObjectRef inputViewBounds() const;
+ void setKeyboardInputModeIdentifier(JSStringRef);
+
void replaceTextAtRange(JSStringRef, int location, int length);
void removeAllDynamicDictionaries();
Modified: trunk/Tools/WebKitTestRunner/PlatformWebView.h (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/PlatformWebView.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/PlatformWebView.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -103,6 +103,8 @@
bool drawsBackground() const;
void setDrawsBackground(bool);
+ void setEditable(bool);
+
void removeFromWindow();
void addToWindow();
Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/TestController.cpp 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp 2018-12-06 21:22:19 UTC (rev 238939)
@@ -1257,6 +1257,8 @@
testOptions.shouldShowSpellCheckingDots = parseBooleanTestHeaderValue(value);
else if (key == "enableEditableImages")
testOptions.enableEditableImages = parseBooleanTestHeaderValue(value);
+ else if (key == "editable")
+ testOptions.editable = parseBooleanTestHeaderValue(value);
pairStart = pairEnd + 1;
}
}
Modified: trunk/Tools/WebKitTestRunner/TestController.h (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/TestController.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/TestController.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -40,9 +40,11 @@
#if PLATFORM(COCOA)
#include "ClassMethodSwizzler.h"
+#include "InstanceMethodSwizzler.h"
#endif
OBJC_CLASS NSString;
+OBJC_CLASS UIKeyboardInputMode;
OBJC_CLASS WKWebViewConfiguration;
namespace WTR {
@@ -270,6 +272,12 @@
RetainPtr<NSString> getOverriddenCalendarIdentifier() const;
void setDefaultCalendarType(NSString *identifier);
#endif // PLATFORM(COCOA)
+
+#if PLATFORM(IOS_FAMILY)
+ void setKeyboardInputModeIdentifier(const String&);
+ UIKeyboardInputMode *overriddenKeyboardInputMode() const { return m_overriddenKeyboardInputMode.get(); }
+#endif
+
private:
WKRetainPtr<WKPageConfigurationRef> generatePageConfiguration(WKContextConfigurationRef);
WKRetainPtr<WKContextConfigurationRef> generateContextConfiguration() const;
@@ -441,6 +449,11 @@
WKRetainPtr<WKContextRef> m_context;
WKRetainPtr<WKPageGroupRef> m_pageGroup;
+#if PLATFORM(IOS_FAMILY)
+ Vector<std::unique_ptr<InstanceMethodSwizzler>> m_inputModeSwizzlers;
+ RetainPtr<UIKeyboardInputMode> m_overriddenKeyboardInputMode;
+#endif
+
enum State {
Initial,
Resetting,
Modified: trunk/Tools/WebKitTestRunner/TestOptions.h (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/TestOptions.h 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/TestOptions.h 2018-12-06 21:22:19 UTC (rev 238939)
@@ -65,6 +65,7 @@
bool shouldIgnoreMetaViewport { false };
bool shouldShowSpellCheckingDots { false };
bool enableEditableImages { false };
+ bool editable { false };
float deviceScaleFactor { 1 };
Vector<String> overrideLanguages;
@@ -107,7 +108,8 @@
|| checkForWorldLeaks != options.checkForWorldLeaks
|| shouldShowSpellCheckingDots != options.shouldShowSpellCheckingDots
|| shouldIgnoreMetaViewport != options.shouldIgnoreMetaViewport
- || enableEditableImages != options.enableEditableImages)
+ || enableEditableImages != options.enableEditableImages
+ || editable != options.editable)
return false;
if (experimentalFeatures != options.experimentalFeatures)
Modified: trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/cocoa/TestControllerCocoa.mm 2018-12-06 21:22:19 UTC (rev 238939)
@@ -171,6 +171,9 @@
if (options.punchOutWhiteBackgroundsInDarkMode)
m_mainWebView->setDrawsBackground(false);
+
+ if (options.editable)
+ m_mainWebView->setEditable(true);
#else
m_mainWebView = std::make_unique<PlatformWebView>(globalWebViewConfiguration, options);
#endif
Modified: trunk/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/gtk/PlatformWebViewGtk.cpp 2018-12-06 21:22:19 UTC (rev 238939)
@@ -198,5 +198,9 @@
{
}
+void PlatformWebView::setEditable(bool)
+{
+}
+
} // namespace WTR
Modified: trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm 2018-12-06 21:22:19 UTC (rev 238939)
@@ -294,6 +294,15 @@
// Retina only surface.
}
+void PlatformWebView::setEditable(bool editable)
+{
+#if WK_API_ENABLED
+ m_view._editable = editable;
+#else
+ UNUSED_PARAM(editable);
+#endif
+}
+
bool PlatformWebView::drawsBackground() const
{
return false;
Modified: trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/ios/TestControllerIOS.mm 2018-12-06 21:22:19 UTC (rev 238939)
@@ -116,6 +116,9 @@
cocoaResetStateToConsistentValues(options);
[[UIDevice currentDevice] setOrientation:UIDeviceOrientationPortrait animated:NO];
+
+ m_inputModeSwizzlers.clear();
+ m_overriddenKeyboardInputMode = nil;
BOOL shouldRestoreFirstResponder = NO;
if (PlatformWebView* platformWebView = mainWebView()) {
@@ -198,4 +201,31 @@
// FIXME: implement for iOS
}
+static UIKeyboardInputMode *swizzleCurrentInputMode()
+{
+ return TestController::singleton().overriddenKeyboardInputMode();
+}
+
+static NSArray<UIKeyboardInputMode *> *swizzleActiveInputModes()
+{
+ return @[ TestController::singleton().overriddenKeyboardInputMode() ];
+}
+
+void TestController::setKeyboardInputModeIdentifier(const String& identifier)
+{
+ m_inputModeSwizzlers.clear();
+ m_overriddenKeyboardInputMode = [UIKeyboardInputMode keyboardInputModeWithIdentifier:identifier];
+ if (!m_overriddenKeyboardInputMode) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ auto controllerClass = UIKeyboardInputModeController.class;
+ m_inputModeSwizzlers.reserveCapacity(3);
+ m_inputModeSwizzlers.uncheckedAppend(std::make_unique<InstanceMethodSwizzler>(controllerClass, @selector(currentInputMode), reinterpret_cast<IMP>(swizzleCurrentInputMode)));
+ m_inputModeSwizzlers.uncheckedAppend(std::make_unique<InstanceMethodSwizzler>(controllerClass, @selector(currentInputModeInPreference), reinterpret_cast<IMP>(swizzleCurrentInputMode)));
+ m_inputModeSwizzlers.uncheckedAppend(std::make_unique<InstanceMethodSwizzler>(controllerClass, @selector(activeInputModes), reinterpret_cast<IMP>(swizzleActiveInputModes)));
+ [UIKeyboardImpl.sharedInstance prepareKeyboardInputModeFromPreferences:nil];
+}
+
} // namespace WTR
Modified: trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2018-12-06 21:22:19 UTC (rev 238939)
@@ -925,6 +925,11 @@
#endif
}
+void UIScriptController::setKeyboardInputModeIdentifier(JSStringRef identifier)
+{
+ TestController::singleton().setKeyboardInputModeIdentifier(toWTFString(toWK(identifier)));
+}
+
void UIScriptController::toggleCapsLock(JSValueRef callback)
{
// FIXME: Implement for iOS. See <https://bugs.webkit.org/show_bug.cgi?id=191815>.
Modified: trunk/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/mac/PlatformWebViewMac.mm 2018-12-06 21:22:19 UTC (rev 238939)
@@ -212,6 +212,15 @@
#endif
}
+void PlatformWebView::setEditable(bool editable)
+{
+#if WK_API_ENABLED
+ m_view._editable = editable;
+#else
+ UNUSED_PARAM(editable);
+#endif
+}
+
RetainPtr<CGImageRef> PlatformWebView::windowSnapshotImage()
{
[platformView() display];
Modified: trunk/Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/win/PlatformWebViewWin.cpp 2018-12-06 21:22:19 UTC (rev 238939)
@@ -259,4 +259,8 @@
{
}
+void PlatformWebView::setEditable(bool)
+{
+}
+
} // namespace WTR
Modified: trunk/Tools/WebKitTestRunner/wpe/PlatformWebViewWPE.cpp (238938 => 238939)
--- trunk/Tools/WebKitTestRunner/wpe/PlatformWebViewWPE.cpp 2018-12-06 20:37:55 UTC (rev 238938)
+++ trunk/Tools/WebKitTestRunner/wpe/PlatformWebViewWPE.cpp 2018-12-06 21:22:19 UTC (rev 238939)
@@ -141,4 +141,8 @@
{
}
+void PlatformWebView::setEditable(bool)
+{
+}
+
} // namespace WTR