Title: [260759] trunk
Revision
260759
Author
[email protected]
Date
2020-04-27 09:08:21 -0700 (Mon, 27 Apr 2020)

Log Message

Caret may be placed in the wrong spot for text input context that is a form control
https://bugs.webkit.org/show_bug.cgi?id=210939
<rdar://problem/61943089>

Reviewed by Darin Adler.

Source/WebCore:

Add a helper function that returns the closest editable position inside an element
for a given point (if any).

* editing/Editing.cpp:
(WebCore::closestEditablePositionInElementForAbsolutePoint): Added.
* editing/Editing.h:

Source/WebKit:

Find the closest editable position in the element for the point using the
newly introduced closestEditablePositionInElementForAbsolutePoint().

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::focusTextInputContextAndPlaceCaret):

Tools:

Add a test.

* TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm:
(TestWebKitAPI::TEST):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (260758 => 260759)


--- trunk/Source/WebCore/ChangeLog	2020-04-27 16:04:30 UTC (rev 260758)
+++ trunk/Source/WebCore/ChangeLog	2020-04-27 16:08:21 UTC (rev 260759)
@@ -1,3 +1,18 @@
+2020-04-27  Daniel Bates  <[email protected]>
+
+        Caret may be placed in the wrong spot for text input context that is a form control
+        https://bugs.webkit.org/show_bug.cgi?id=210939
+        <rdar://problem/61943089>
+
+        Reviewed by Darin Adler.
+
+        Add a helper function that returns the closest editable position inside an element
+        for a given point (if any).
+
+        * editing/Editing.cpp:
+        (WebCore::closestEditablePositionInElementForAbsolutePoint): Added.
+        * editing/Editing.h:
+
 2020-04-27  Alicia Boya GarcĂ­a  <[email protected]>
 
         [GStreamer] Rework WebKitWebSrc threading

Modified: trunk/Source/WebCore/editing/Editing.cpp (260758 => 260759)


--- trunk/Source/WebCore/editing/Editing.cpp	2020-04-27 16:04:30 UTC (rev 260758)
+++ trunk/Source/WebCore/editing/Editing.cpp	2020-04-27 16:08:21 UTC (rev 260759)
@@ -50,8 +50,10 @@
 #include "RenderBlock.h"
 #include "RenderElement.h"
 #include "RenderTableCell.h"
+#include "RenderTextControlSingleLine.h"
 #include "ShadowRoot.h"
 #include "Text.h"
+#include "TextControlInnerElements.h"
 #include "TextIterator.h"
 #include "VisibleUnits.h"
 #include <wtf/Assertions.h>
@@ -561,6 +563,33 @@
     return positionInParentAfterNode(&node);
 }
 
+VisiblePosition closestEditablePositionInElementForAbsolutePoint(const Element& element, const IntPoint& point)
+{
+    if (!element.isConnected() || !element.document().frame())
+        return { };
+
+    Ref<const Element> protectedElement { element };
+    auto frame = makeRef(*element.document().frame());
+
+    element.document().updateLayoutIgnorePendingStylesheets();
+
+    RenderObject* renderer = element.renderer();
+    // Look at the inner element of a form control, not the control itself, as it is the editable part.
+    if (is<HTMLTextFormControlElement>(element)) {
+        auto& formControlElement = downcast<HTMLTextFormControlElement>(element);
+        if (!formControlElement.isInnerTextElementEditable())
+            return { };
+        if (auto innerTextElement = formControlElement.innerTextElement())
+            renderer = innerTextElement->renderer();
+    }
+    if (!renderer)
+        return { };
+    auto absoluteBoundingBox = renderer->absoluteBoundingBoxRect();
+    auto constrainedPoint = point.constrainedBetween(absoluteBoundingBox.minXMinYCorner(), absoluteBoundingBox.maxXMaxYCorner());
+    auto visiblePosition = frame->visiblePositionForPoint(constrainedPoint);
+    return isEditablePosition(visiblePosition.deepEquivalent()) ? visiblePosition : VisiblePosition { };
+}
+
 bool isListHTMLElement(Node* node)
 {
     return node && (is<HTMLUListElement>(*node) || is<HTMLOListElement>(*node) || is<HTMLDListElement>(*node));

Modified: trunk/Source/WebCore/editing/Editing.h (260758 => 260759)


--- trunk/Source/WebCore/editing/Editing.h	2020-04-27 16:04:30 UTC (rev 260758)
+++ trunk/Source/WebCore/editing/Editing.h	2020-04-27 16:08:21 UTC (rev 260759)
@@ -156,6 +156,8 @@
 WEBCORE_EXPORT VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope);
 VisiblePosition visiblePositionForIndexUsingCharacterIterator(Node&, int index); // FIXME: Why do we need this version?
 
+WEBCORE_EXPORT VisiblePosition closestEditablePositionInElementForAbsolutePoint(const Element&, const IntPoint&);
+
 // -------------------------------------------------------------------------
 // HTMLElement
 // -------------------------------------------------------------------------

Modified: trunk/Source/WebKit/ChangeLog (260758 => 260759)


--- trunk/Source/WebKit/ChangeLog	2020-04-27 16:04:30 UTC (rev 260758)
+++ trunk/Source/WebKit/ChangeLog	2020-04-27 16:08:21 UTC (rev 260759)
@@ -1,3 +1,17 @@
+2020-04-27  Daniel Bates  <[email protected]>
+
+        Caret may be placed in the wrong spot for text input context that is a form control
+        https://bugs.webkit.org/show_bug.cgi?id=210939
+        <rdar://problem/61943089>
+
+        Reviewed by Darin Adler.
+
+        Find the closest editable position in the element for the point using the
+        newly introduced closestEditablePositionInElementForAbsolutePoint().
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::focusTextInputContextAndPlaceCaret):
+
 2020-04-27  Darin Adler  <[email protected]>
 
         Fix ENABLE(PLATFORM_DRIVEN_TEXT_CHECKING) build

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (260758 => 260759)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2020-04-27 16:04:30 UTC (rev 260758)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2020-04-27 16:08:21 UTC (rev 260759)
@@ -99,7 +99,6 @@
 #import <WebCore/HTMLSelectElement.h>
 #import <WebCore/HTMLSummaryElement.h>
 #import <WebCore/HTMLTextAreaElement.h>
-#import <WebCore/HTMLTextFormControlElement.h>
 #import <WebCore/HistoryItem.h>
 #import <WebCore/HitTestResult.h>
 #import <WebCore/InputMode.h>
@@ -4350,6 +4349,8 @@
         return;
     }
 
+    // FIXME: Do not focus an element if it moved or the caret point is outside its bounds
+    // because we only want to do so if the caret can be placed.
     UserGestureIndicator gestureIndicator { ProcessingUserGesture, &target->document() };
     SetForScope<bool> userIsInteractingChange { m_userIsInteracting, true };
     m_page->focusController().setFocusedElement(target.get(), targetFrame);
@@ -4359,9 +4360,13 @@
         completionHandler(false);
         return;
     }
-    // The function visiblePositionInFocusedNodeForPoint constrains the point to be inside
-    // the bounds of the target element.
-    auto position = visiblePositionInFocusedNodeForPoint(targetFrame, point, true /* isInteractingWithFocusedElement */);
+
+    ASSERT(targetFrame->view());
+    auto position = closestEditablePositionInElementForAbsolutePoint(*target, targetFrame->view()->rootViewToContents(point));
+    if (position.isNull()) {
+        completionHandler(false);
+        return;
+    }
     targetFrame->selection().setSelectedRange(Range::create(*targetFrame->document(), position, position).ptr(), position.affinity(), WebCore::FrameSelection::ShouldCloseTyping::Yes, UserTriggered);
     completionHandler(true);
 }

Modified: trunk/Tools/ChangeLog (260758 => 260759)


--- trunk/Tools/ChangeLog	2020-04-27 16:04:30 UTC (rev 260758)
+++ trunk/Tools/ChangeLog	2020-04-27 16:08:21 UTC (rev 260759)
@@ -1,3 +1,16 @@
+2020-04-27  Daniel Bates  <[email protected]>
+
+        Caret may be placed in the wrong spot for text input context that is a form control
+        https://bugs.webkit.org/show_bug.cgi?id=210939
+        <rdar://problem/61943089>
+
+        Reviewed by Darin Adler.
+
+        Add a test.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm:
+        (TestWebKitAPI::TEST):
+
 2020-04-27  Alexey Proskuryakov  <[email protected]>
 
         Make run-safari --ios-simulator work again

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm (260758 => 260759)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm	2020-04-27 16:04:30 UTC (rev 260758)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/RequestTextInputContext.mm	2020-04-27 16:08:21 UTC (rev 260759)
@@ -464,6 +464,26 @@
     EXPECT_EQ(static_cast<int>(exampleTextLength), [[webView objectByEvaluatingJavaScript:@"document.activeElement.selectionEnd"] intValue]);
 }
 
+TEST(RequestTextInputContext, FocusFieldWithPaddingAndPlaceCaretAtEnd)
+{
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+
+    constexpr char exampleText[] = "hello world";
+    constexpr size_t exampleTextLength = sizeof(exampleText) - 1;
+    [webView synchronouslyLoadHTMLString:applyStyle([NSString stringWithFormat:@"<input type='text' value='%s' style='width: 100px; height: 50px; padding: 20px'>", exampleText])];
+    NSArray<_WKTextInputContext *> *contexts = [webView synchronouslyRequestTextInputContextsInRect:[webView bounds]];
+    EXPECT_EQ(1UL, contexts.count);
+    RetainPtr<_WKTextInputContext> inputElement = contexts[0];
+
+    CGRect boundingRect = [inputElement boundingRect];
+    CGPoint endPosition = CGPointMake(boundingRect.origin.x + boundingRect.size.width, boundingRect.origin.y);
+    EXPECT_EQ((UIResponder<UITextInput> *)[webView textInputContentView], [webView synchronouslyFocusTextInputContext:inputElement.get() placeCaretAt:endPosition]);
+    EXPECT_WK_STREQ("INPUT", [webView stringByEvaluatingJavaScript:@"document.activeElement.tagName"]);
+    EXPECT_EQ(static_cast<int>(exampleTextLength), [[webView objectByEvaluatingJavaScript:@"document.activeElement.selectionStart"] intValue]);
+    EXPECT_EQ(static_cast<int>(exampleTextLength), [[webView objectByEvaluatingJavaScript:@"document.activeElement.selectionEnd"] intValue]);
+}
+
 TEST(RequestTextInputContext, FocusFieldAndPlaceCaretOutsideField)
 {
     auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to