AX: Typing broken on form input field while using VoiceOver
authorn_wang@apple.com <n_wang@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Mar 2016 17:44:00 +0000 (17:44 +0000)
committern_wang@apple.com <n_wang@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 18 Mar 2016 17:44:00 +0000 (17:44 +0000)
https://bugs.webkit.org/show_bug.cgi?id=155613

Reviewed by Chris Fleizach.

Source/WebCore:

The div element inside the INPUT element gives a collapsed TextMarkerRange which then creates
a collapsed Range. Fixed it by using the parent node to create the Range when the div node has
no children.

Test: accessibility/mac/text-marker-range-for-node-without-children.html

* accessibility/AXObjectCache.cpp:
(WebCore::setRangeStartOrEndWithCharacterOffset):

LayoutTests:

* accessibility/mac/text-marker-range-for-node-without-children-expected.txt: Added.
* accessibility/mac/text-marker-range-for-node-without-children.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/accessibility/mac/text-marker-range-for-node-without-children-expected.txt [new file with mode: 0644]
LayoutTests/accessibility/mac/text-marker-range-for-node-without-children.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/accessibility/AXObjectCache.cpp

index c6d385be007649b27f586600be4cbe301c5d4726..9485975e223698432ced7e8abe808e8bdc1766b1 100644 (file)
@@ -1,3 +1,13 @@
+2016-03-18  Nan Wang  <n_wang@apple.com>
+
+        AX: Typing broken on form input field while using VoiceOver
+        https://bugs.webkit.org/show_bug.cgi?id=155613
+
+        Reviewed by Chris Fleizach.
+
+        * accessibility/mac/text-marker-range-for-node-without-children-expected.txt: Added.
+        * accessibility/mac/text-marker-range-for-node-without-children.html: Added.
+
 2016-03-18  Youenn Fablet  <youenn.fablet@crf.canon.fr>
 
         crossorigin element resource loading should check HTTP redirection
diff --git a/LayoutTests/accessibility/mac/text-marker-range-for-node-without-children-expected.txt b/LayoutTests/accessibility/mac/text-marker-range-for-node-without-children-expected.txt
new file mode 100644 (file)
index 0000000..102f4e7
--- /dev/null
@@ -0,0 +1,14 @@
+a
+b
+This tests that creating TextMarkerRange from nodes that have no children won't collapse to one side.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS textbox.textMarkerRangeLength(textboxRange) == 1 is true
+PASS textbox.accessibilityElementForTextMarker(startMarker).description is 'AXDescription: parent level'
+PASS textbox.accessibilityElementForTextMarker(endMarker).description is 'AXDescription: parent level'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/accessibility/mac/text-marker-range-for-node-without-children.html b/LayoutTests/accessibility/mac/text-marker-range-for-node-without-children.html
new file mode 100644 (file)
index 0000000..f698c64
--- /dev/null
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+
+<div id="container" aria-label="parent level">
+a <div id="textbox" aria-label="child level" contenteditable="true"></div> b
+</div>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+    description("This tests that creating TextMarkerRange from nodes that have no children won't collapse to one side.");
+    
+    if (window.accessibilityController) {
+        var textbox = accessibilityController.accessibleElementById("textbox");
+        var textboxRange = textbox.textMarkerRangeForElement(textbox);
+        // The range should include the div element. 
+        shouldBeTrue("textbox.textMarkerRangeLength(textboxRange) == 1");
+        
+        // Make sure the node that associates with the text marker is the parent div element.
+        var startMarker = textbox.startTextMarkerForTextMarkerRange(textboxRange);
+        var endMarker = textbox.endTextMarkerForTextMarkerRange(textboxRange);
+        shouldBe("textbox.accessibilityElementForTextMarker(startMarker).description", "'AXDescription: parent level'");
+        shouldBe("textbox.accessibilityElementForTextMarker(endMarker).description", "'AXDescription: parent level'");
+    }
+</script>
+
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
index be7899bdc0ab07b1944d0a781a35762da6936cfb..9f7615f1af124c2b5a3f321e0539a4b83bcded47 100644 (file)
@@ -1,3 +1,19 @@
+2016-03-18  Nan Wang  <n_wang@apple.com>
+
+        AX: Typing broken on form input field while using VoiceOver
+        https://bugs.webkit.org/show_bug.cgi?id=155613
+
+        Reviewed by Chris Fleizach.
+
+        The div element inside the INPUT element gives a collapsed TextMarkerRange which then creates
+        a collapsed Range. Fixed it by using the parent node to create the Range when the div node has
+        no children.
+
+        Test: accessibility/mac/text-marker-range-for-node-without-children.html
+
+        * accessibility/AXObjectCache.cpp:
+        (WebCore::setRangeStartOrEndWithCharacterOffset):
+
 2016-03-18  Chris Fleizach  <cfleizach@apple.com>
 
         AX: Implement AutoFill Available attribute for a text field
index 151e9e75e6e916b03f761526aea9b5835510433c..27f39842f05302fbcb33e43f026dc0d8dcd0997d 100644 (file)
@@ -1630,8 +1630,15 @@ static void setRangeStartOrEndWithCharacterOffset(RefPtr<Range> range, const Cha
     
     int offset = characterOffset.startIndex + characterOffset.offset;
     Node* node = characterOffset.node;
-    if (isReplacedNodeOrBR(node))
-        node = resetNodeAndOffsetForReplacedNode(node, offset, characterOffset.offset);
+    
+    bool replacedNodeOrBR = isReplacedNodeOrBR(node);
+    // For the non text node that has no children, we should create the range with its parent, otherwise the range would be collapsed.
+    // Example: <div contenteditable="true"></div>, we want the range to include the div element.
+    bool noChildren = !replacedNodeOrBR && !node->isTextNode() && !node->hasChildNodes();
+    int characterCount = noChildren ? (isStart ? 0 : 1) : characterOffset.offset;
+    
+    if (replacedNodeOrBR || noChildren)
+        node = resetNodeAndOffsetForReplacedNode(node, offset, characterCount);
     
     if (isStart)
         range->setStart(node, offset, ec);