API test WebKit.RequestTextInputContext fails on iOS
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Mar 2019 01:53:58 +0000 (01:53 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 12 Mar 2019 01:53:58 +0000 (01:53 +0000)
https://bugs.webkit.org/show_bug.cgi?id=195585

Reviewed by Wenson Hsieh and Simon Fraser.

Source/WebKit:

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _convertRectFromRootViewCoordinates:]):
(-[WKWebView _convertRectToRootViewCoordinates:]):
(-[WKWebView _requestTextInputContextsInRect:completionHandler:]):
(-[WKWebView _focusTextInputContext:completionHandler:]):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::elementRectInRootViewCoordinates):
(WebKit::WebPage::textInputContextsInRect):
(WebKit::elementRectInWindowCoordinates): Deleted.
Text input context SPI should be in terms of WKWebView coordinates,
for consistency's sake. This is a bit irritating; WebPage(Proxy) continue
to operate in "root view" coordinates, which means different things
depending on if delegatesScrolling is true or not. So, WKWebView does
the conversion, re-creating objects as needed.

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm:
(applyStyle):
(TEST):
Add a viewport, so that the coordinates match up on iOS.
Scroll by moving the UIScrollView's contentOffset.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@242762 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit/ChangeLog
Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit/WebProcess/WebPage/WebPage.cpp
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm

index 0c7ef17..3b0472b 100644 (file)
@@ -1,3 +1,25 @@
+2019-03-11  Tim Horton  <timothy_horton@apple.com>
+
+        API test WebKit.RequestTextInputContext fails on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=195585
+
+        Reviewed by Wenson Hsieh and Simon Fraser.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _convertRectFromRootViewCoordinates:]):
+        (-[WKWebView _convertRectToRootViewCoordinates:]):
+        (-[WKWebView _requestTextInputContextsInRect:completionHandler:]):
+        (-[WKWebView _focusTextInputContext:completionHandler:]):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::elementRectInRootViewCoordinates):
+        (WebKit::WebPage::textInputContextsInRect):
+        (WebKit::elementRectInWindowCoordinates): Deleted.
+        Text input context SPI should be in terms of WKWebView coordinates,
+        for consistency's sake. This is a bit irritating; WebPage(Proxy) continue
+        to operate in "root view" coordinates, which means different things
+        depending on if delegatesScrolling is true or not. So, WKWebView does
+        the conversion, re-creating objects as needed.
+
 2019-03-09  Jiewen Tan  <jiewen_tan@apple.com>
 
         Optimizing loads when creating new pages
index d2d28eb..f9dac4a 100644 (file)
@@ -4838,13 +4838,47 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
     }
 }
 
-- (void)_requestTextInputContextsInRect:(CGRect)rect completionHandler:(void(^)(NSArray<_WKTextInputContext *> *))completionHandler
+- (CGRect)_convertRectFromRootViewCoordinates:(CGRect)rectInRootViewCoordinates
 {
-    _page->textInputContextsInRect(rect, [capturedCompletionHandler = makeBlockPtr(completionHandler)] (const Vector<WebKit::TextInputContext>& contexts) {
+    // FIXME: It should be easier to talk about WKWebView coordinates in a consistent and cross-platform way.
+    // Currently, neither "root view" nor "window" mean "WKWebView coordinates" on both platforms.
+    // See https://webkit.org/b/193649 and related bugs.
+#if PLATFORM(IOS_FAMILY)
+    return [self convertRect:rectInRootViewCoordinates fromView:_contentView.get()];
+#else
+    return rectInRootViewCoordinates;
+#endif
+}
+
+- (CGRect)_convertRectToRootViewCoordinates:(CGRect)rectInWebViewCoordinates
+{
+#if PLATFORM(IOS_FAMILY)
+    return [self convertRect:rectInWebViewCoordinates toView:_contentView.get()];
+#else
+    return rectInWebViewCoordinates;
+#endif
+}
+
+- (void)_requestTextInputContextsInRect:(CGRect)rectInWebViewCoordinates completionHandler:(void(^)(NSArray<_WKTextInputContext *> *))completionHandler
+{
+#if PLATFORM(IOS_FAMILY)
+    if (![self usesStandardContentView]) {
+        completionHandler(@[]);
+        return;
+    }
+#endif
+
+    CGRect rectInRootViewCoordinates = [self _convertRectToRootViewCoordinates:rectInWebViewCoordinates];
+    auto weakSelf = WeakObjCPtr<WKWebView>(self);
+    _page->textInputContextsInRect(rectInRootViewCoordinates, [weakSelf, capturedCompletionHandler = makeBlockPtr(completionHandler)] (const Vector<WebKit::TextInputContext>& contexts) {
         RetainPtr<NSMutableArray> elements = adoptNS([[NSMutableArray alloc] initWithCapacity:contexts.size()]);
 
-        for (const auto& context : contexts)
-            [elements addObject:adoptNS([[_WKTextInputContext alloc] _initWithTextInputContext:context]).get()];
+        auto strongSelf = weakSelf.get();
+        for (const auto& context : contexts) {
+            WebKit::TextInputContext contextWithWebViewBoundingRect = context;
+            contextWithWebViewBoundingRect.boundingRect = [strongSelf _convertRectFromRootViewCoordinates:context.boundingRect];
+            [elements addObject:adoptNS([[_WKTextInputContext alloc] _initWithTextInputContext:contextWithWebViewBoundingRect]).get()];
+        }
 
         capturedCompletionHandler(elements.get());
     });
@@ -4852,6 +4886,13 @@ FOR_EACH_PRIVATE_WKCONTENTVIEW_ACTION(FORWARD_ACTION_TO_WKCONTENTVIEW)
 
 - (void)_focusTextInputContext:(_WKTextInputContext *)textInputContext completionHandler:(void(^)(BOOL))completionHandler
 {
+#if PLATFORM(IOS_FAMILY)
+    if (![self usesStandardContentView]) {
+        completionHandler(NO);
+        return;
+    }
+#endif
+
     auto webContext = [textInputContext _textInputContext];
     if (webContext.webPageIdentifier != _page->pageID())
         [NSException raise:NSInvalidArgumentException format:@"The provided _WKTextInputContext was not created by this WKWebView."];
index 41e152a..0cbd0d4 100644 (file)
@@ -6468,7 +6468,7 @@ WebCore::IntRect WebPage::rectForElementAtInteractionLocation() const
 
 #endif // !PLATFORM(IOS_FAMILY)
 
-static IntRect elementRectInWindowCoordinates(const Element& element, const Frame& frame)
+static IntRect elementRectInRootViewCoordinates(const Element& element, const Frame& frame)
 {
     auto* view = frame.view();
     if (!view)
@@ -6478,7 +6478,7 @@ static IntRect elementRectInWindowCoordinates(const Element& element, const Fram
     if (!renderer)
         return { };
 
-    return view->contentsToWindow(renderer->absoluteBoundingBoxRect());
+    return view->contentsToRootView(renderer->absoluteBoundingBoxRect());
 }
 
 static bool isEditableTextInputElement(Element& element)
@@ -6516,7 +6516,7 @@ void WebPage::textInputContextsInRect(WebCore::FloatRect searchRect, CompletionH
 
             auto& element = downcast<Element>(*node);
 
-            IntRect elementRect = elementRectInWindowCoordinates(element, *frame);
+            IntRect elementRect = elementRectInRootViewCoordinates(element, *frame);
             if (!searchRect.intersects(elementRect))
                 continue;
 
index 9fd2305..fe2e2c0 100644 (file)
@@ -1,3 +1,16 @@
+2019-03-11  Tim Horton  <timothy_horton@apple.com>
+
+        API test WebKit.RequestTextInputContext fails on iOS
+        https://bugs.webkit.org/show_bug.cgi?id=195585
+
+        Reviewed by Wenson Hsieh and Simon Fraser.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm:
+        (applyStyle):
+        (TEST):
+        Add a viewport, so that the coordinates match up on iOS.
+        Scroll by moving the UIScrollView's contentOffset.
+
 2019-03-11  Chris Dumez  <cdumez@apple.com>
 
         Assert in WebPageProxy::suspendCurrentPageIfPossible()
index bda3dd6..a53ba43 100644 (file)
@@ -71,7 +71,7 @@
 
 static NSString *applyStyle(NSString *HTMLString)
 {
-    return [@"<style>body { margin: 0; } iframe { border: none; }</style>" stringByAppendingString:HTMLString];
+    return [@"<style>body { margin: 0; } iframe { border: none; }</style><meta name='viewport' content='initial-scale=1'>" stringByAppendingString:HTMLString];
 }
 
 static NSString *applyIframe(NSString *HTMLString)
@@ -140,16 +140,22 @@ TEST(WebKit, RequestTextInputContext)
     // Inputs scrolled outside the requested rect; should not be included.
 
     [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px;'><br><div style='width: 100px; height: 5000px;'></div>")];
+#if PLATFORM(MAC)
     [webView objectByEvaluatingJavaScript:@"window.scrollTo(0, 5000);"];
-    [webView waitForNextPresentationUpdate];
+#else
+    [webView scrollView].contentOffset = CGPointMake(0, 5000);
+#endif
     contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
     EXPECT_EQ(0UL, contexts.count);
 
     // Inputs scrolled into the requested rect.
 
     [webView synchronouslyLoadHTMLString:applyStyle(@"<input type='text' style='width: 50px; height: 50px; position: absolute; top: 5000px;'><br><div style='width: 100px; height: 10000px;'></div>")];
+#if PLATFORM(MAC)
     [webView objectByEvaluatingJavaScript:@"window.scrollTo(0, 5000);"];
-    [webView waitForNextPresentationUpdate];
+#else
+    [webView scrollView].contentOffset = CGPointMake(0, 5000);
+#endif
     contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView frame]];
     EXPECT_EQ(1UL, contexts.count);
     EXPECT_RECT_EQ(0, 0, 50, 50, contexts[0].boundingRect);