- 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]);