Title: [260678] trunk
Revision
260678
Author
[email protected]
Date
2020-04-24 16:18:05 -0700 (Fri, 24 Apr 2020)

Log Message

Make some more adjustments to TextManipulationController's paragraph boundary heuristic
https://bugs.webkit.org/show_bug.cgi?id=210993
<rdar://problem/61571299>

Reviewed by Tim Horton.

Source/WebCore:

Adjust the heuristic added in r260583 to account for a few more common scenarios where we currently consider
text as a part of the same paragraph. This can lead to many issues during text manipulation where text is moved
between these elements, when it should not be.

The new scenarios include block and inline-block links, as well as button elements.

Test: TextManipulation.StartTextManipulationTreatsInlineBlockLinksAndButtonsAsParagraphs

* editing/TextManipulationController.cpp:
(WebCore::TextManipulationController::observeParagraphs):

Additionally rename "paragraph boundary element" to "item boundary element", to avoid colliding with the
existing notion of paragraph boundaries in editing code.

Tools:

Add a new API test with buttons and links styled with `display: inline-block;`. Additionally, rebaseline an
existing API test that exercises inline-block list items.

* TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (260677 => 260678)


--- trunk/Source/WebCore/ChangeLog	2020-04-24 22:49:18 UTC (rev 260677)
+++ trunk/Source/WebCore/ChangeLog	2020-04-24 23:18:05 UTC (rev 260678)
@@ -1,3 +1,25 @@
+2020-04-24  Wenson Hsieh  <[email protected]>
+
+        Make some more adjustments to TextManipulationController's paragraph boundary heuristic
+        https://bugs.webkit.org/show_bug.cgi?id=210993
+        <rdar://problem/61571299>
+
+        Reviewed by Tim Horton.
+
+        Adjust the heuristic added in r260583 to account for a few more common scenarios where we currently consider
+        text as a part of the same paragraph. This can lead to many issues during text manipulation where text is moved
+        between these elements, when it should not be.
+
+        The new scenarios include block and inline-block links, as well as button elements.
+
+        Test: TextManipulation.StartTextManipulationTreatsInlineBlockLinksAndButtonsAsParagraphs
+
+        * editing/TextManipulationController.cpp:
+        (WebCore::TextManipulationController::observeParagraphs):
+
+        Additionally rename "paragraph boundary element" to "item boundary element", to avoid colliding with the
+        existing notion of paragraph boundaries in editing code.
+
 2020-04-24  Christopher Reid  <[email protected]>
 
         [Win] Bundle Inspector Resources in Release builds

Modified: trunk/Source/WebCore/editing/TextManipulationController.cpp (260677 => 260678)


--- trunk/Source/WebCore/editing/TextManipulationController.cpp	2020-04-24 22:49:18 UTC (rev 260677)
+++ trunk/Source/WebCore/editing/TextManipulationController.cpp	2020-04-24 23:18:05 UTC (rev 260678)
@@ -274,13 +274,21 @@
     Vector<ManipulationToken> tokensInCurrentParagraph;
     Position startOfCurrentParagraph;
     Position endOfCurrentParagraph;
-    RefPtr<Element> enclosingParagraphElement;
+    RefPtr<Element> enclosingItemBoundaryElement;
 
-    auto isEnclosingParagraphElement = [](const Element& element) {
-        if (element.hasTagName(HTMLNames::liTag)) {
-            auto* renderer = element.renderer();
-            return renderer && renderer->style().display() == DisplayType::Block;
+    auto isEnclosingItemBoundaryElement = [](const Element& element) {
+        auto* renderer = element.renderer();
+        if (!renderer)
+            return false;
+
+        if (element.hasTagName(HTMLNames::buttonTag))
+            return true;
+
+        if (element.hasTagName(HTMLNames::liTag) || element.hasTagName(HTMLNames::aTag)) {
+            auto displayType = renderer->style().display();
+            return displayType == DisplayType::Block || displayType == DisplayType::InlineBlock;
         }
+
         return false;
     };
 
@@ -287,11 +295,12 @@
     for (; !iterator.atEnd(); iterator.advance()) {
         auto content = iterator.currentContent();
         if (content.node) {
-            if (enclosingParagraphElement && !enclosingParagraphElement->contains(content.node.get())) {
+            if (enclosingItemBoundaryElement && !enclosingItemBoundaryElement->contains(content.node.get())) {
                 if (!tokensInCurrentParagraph.isEmpty())
                     addItem(ManipulationItemData { startOfCurrentParagraph, endOfCurrentParagraph, nullptr, nullQName(), std::exchange(tokensInCurrentParagraph, { }) });
-                enclosingParagraphElement = nullptr;
+                enclosingItemBoundaryElement = nullptr;
             }
+
             if (RefPtr<Element> currentElementAncestor = is<Element>(*content.node) ? downcast<Element>(content.node.get()) : content.node->parentOrShadowHostElement()) {
                 if (isInManipulatedElement(*currentElementAncestor))
                     return; // We can exit early here because scheduleObservartionUpdate calls this function on each paragraph separately.
@@ -311,8 +320,8 @@
                         }
                     }
                 }
-                if (isEnclosingParagraphElement(currentElement))
-                    enclosingParagraphElement = &currentElement;
+                if (!enclosingItemBoundaryElement && isEnclosingItemBoundaryElement(currentElement))
+                    enclosingItemBoundaryElement = &currentElement;
             }
         }
 

Modified: trunk/Tools/ChangeLog (260677 => 260678)


--- trunk/Tools/ChangeLog	2020-04-24 22:49:18 UTC (rev 260677)
+++ trunk/Tools/ChangeLog	2020-04-24 23:18:05 UTC (rev 260678)
@@ -1,3 +1,16 @@
+2020-04-24  Wenson Hsieh  <[email protected]>
+
+        Make some more adjustments to TextManipulationController's paragraph boundary heuristic
+        https://bugs.webkit.org/show_bug.cgi?id=210993
+        <rdar://problem/61571299>
+
+        Reviewed by Tim Horton.
+
+        Add a new API test with buttons and links styled with `display: inline-block;`. Additionally, rebaseline an
+        existing API test that exercises inline-block list items.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm:
+
 2020-04-24  Chris Dumez  <[email protected]>
 
         [iOS] Always run WKTR's WKWebViews at foreground priority

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm (260677 => 260678)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm	2020-04-24 22:49:18 UTC (rev 260677)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/TextManipulation.mm	2020-04-24 23:18:05 UTC (rev 260678)
@@ -616,6 +616,46 @@
     EXPECT_WK_STREQ("More text", items[1].tokens[0].content);
 }
 
+TEST(TextManipulation, StartTextManipulationTreatsInlineBlockLinksAndButtonsAsParagraphs)
+{
+    auto delegate = adoptNS([[TextManipulationDelegate alloc] init]);
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:NSMakeRect(0, 0, 400, 400)]);
+    [webView _setTextManipulationDelegate:delegate.get()];
+
+    [webView synchronouslyLoadHTMLString:@"<!DOCTYPE html>"
+        "<head>"
+        "    <style>"
+        "        a {"
+        "            display: inline-block;"
+        "            border: 1px blue solid;"
+        "            margin-left: 1em;"
+        "        }"
+        "    </style>"
+        "</head>"
+        "<body>"
+        "    <button>One</button><button>Two</button>"
+        "    <div><br></div>"
+        "    <a href=''>Three</a><a href=''>Four</a>"
+        "</body>"];
+
+    done = false;
+    [webView _startTextManipulationsWithConfiguration:nil completion:^{
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    NSArray<_WKTextManipulationItem *> *items = [delegate items];
+    EXPECT_EQ(items.count, 4UL);
+    EXPECT_EQ(items[0].tokens.count, 1UL);
+    EXPECT_EQ(items[1].tokens.count, 1UL);
+    EXPECT_EQ(items[2].tokens.count, 1UL);
+    EXPECT_EQ(items[3].tokens.count, 1UL);
+    EXPECT_WK_STREQ("One", items[0].tokens[0].content);
+    EXPECT_WK_STREQ("Two", items[1].tokens[0].content);
+    EXPECT_WK_STREQ("Three", items[2].tokens[0].content);
+    EXPECT_WK_STREQ("Four", items[3].tokens[0].content);
+}
+
 struct Token {
     NSString *identifier;
     NSString *content;
@@ -1778,16 +1818,17 @@
     TestWebKitAPI::Util::run(&done);
 
     auto *items = [delegate items];
-    EXPECT_EQ(items.count, 1UL);
-    EXPECT_EQ(items[0].tokens.count, 2UL);
-    EXPECT_STREQ("holle", items[0].tokens[0].content.UTF8String);
-    EXPECT_STREQ("wdrlo", items[0].tokens[1].content.UTF8String);
+    EXPECT_EQ(items.count, 2UL);
+    EXPECT_EQ(items[0].tokens.count, 1UL);
+    EXPECT_EQ(items[1].tokens.count, 1UL);
+    EXPECT_WK_STREQ("holle", items[0].tokens[0].content);
+    EXPECT_WK_STREQ("wdrlo", items[1].tokens[0].content);
 
     done = false;
-    [webView _completeTextManipulationForItems:@[(_WKTextManipulationItem *)createItem(items[0].identifier, {
-        { items[0].tokens[0].identifier, @"hello" },
-        { items[0].tokens[1].identifier, @"world" },
-    })] completion:^(NSArray<NSError *> *errors) {
+    [webView _completeTextManipulationForItems:@[
+        createItem(items[0].identifier, {{ items[0].tokens[0].identifier, @"hello" }}).autorelease(),
+        createItem(items[1].identifier, {{ items[1].tokens[0].identifier, @"world" }}).autorelease()
+    ] completion:^(NSArray<NSError *> *errors) {
         EXPECT_EQ(errors, nil);
         done = true;
     }];
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to