Log Message
[GTK][a11y] Embedded objects are not correctly handled by text interface with ATSPI https://bugs.webkit.org/show_bug.cgi?id=232622
Reviewed by Andres Gonzalez. Source/WebCore: Make sure text iterator is emitting object replacement characters when converting offsets to/from visible positions. * accessibility/AccessibilityRenderObject.cpp: (WebCore::AccessibilityRenderObject::visiblePositionForIndex const): (WebCore::AccessibilityRenderObject::indexForVisiblePosition const): * accessibility/atspi/AccessibilityObjectTextAtspi.cpp: (WebCore::AccessibilityObjectAtspi::boundsForSelection const): * editing/Editing.cpp: (WebCore::indexForVisiblePosition): (WebCore::visiblePositionForIndex): * editing/Editing.h: Tools: Add a test case to check handling of embedded objects by text interface. * TestWebKitAPI/Tests/WebKitGtk/TestWebKitAccessibility.cpp: (testTextReplacedObjects): (beforeAll):
Modified Paths
- trunk/Source/WebCore/ChangeLog
- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
- trunk/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp
- trunk/Source/WebCore/editing/Editing.cpp
- trunk/Source/WebCore/editing/Editing.h
- trunk/Tools/ChangeLog
- trunk/Tools/TestWebKitAPI/Tests/WebKitGtk/TestWebKitAccessibility.cpp
Diff
Modified: trunk/Source/WebCore/ChangeLog (285338 => 285339)
--- trunk/Source/WebCore/ChangeLog 2021-11-05 08:21:13 UTC (rev 285338)
+++ trunk/Source/WebCore/ChangeLog 2021-11-05 08:22:39 UTC (rev 285339)
@@ -1,5 +1,24 @@
2021-11-05 Carlos Garcia Campos <[email protected]>
+ [GTK][a11y] Embedded objects are not correctly handled by text interface with ATSPI
+ https://bugs.webkit.org/show_bug.cgi?id=232622
+
+ Reviewed by Andres Gonzalez.
+
+ Make sure text iterator is emitting object replacement characters when converting offsets to/from visible positions.
+
+ * accessibility/AccessibilityRenderObject.cpp:
+ (WebCore::AccessibilityRenderObject::visiblePositionForIndex const):
+ (WebCore::AccessibilityRenderObject::indexForVisiblePosition const):
+ * accessibility/atspi/AccessibilityObjectTextAtspi.cpp:
+ (WebCore::AccessibilityObjectAtspi::boundsForSelection const):
+ * editing/Editing.cpp:
+ (WebCore::indexForVisiblePosition):
+ (WebCore::visiblePositionForIndex):
+ * editing/Editing.h:
+
+2021-11-05 Carlos Garcia Campos <[email protected]>
+
Unreviewed. [GTK][WPE] Fix compile warning after r284675
* accessibility/AXObjectCache.cpp:
Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp (285338 => 285339)
--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp 2021-11-05 08:21:13 UTC (rev 285338)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp 2021-11-05 08:22:39 UTC (rev 285339)
@@ -2145,7 +2145,12 @@
if (!node)
return VisiblePosition();
+#if USE(ATSPI)
+ // We need to consider replaced elements for GTK, as they will be presented with the 'object replacement character' (0xFFFC).
+ return WebCore::visiblePositionForIndex(index, node, TextIteratorBehavior::EmitsObjectReplacementCharacters);
+#else
return visiblePositionForIndexUsingCharacterIterator(*node, index);
+#endif
}
int AccessibilityRenderObject::indexForVisiblePosition(const VisiblePosition& position) const
@@ -2163,15 +2168,16 @@
if (!node)
return 0;
-#if USE(ATK) || USE(ATSPI)
// We need to consider replaced elements for GTK, as they will be
// presented with the 'object replacement character' (0xFFFC).
- bool forSelectionPreservation = true;
-#else
- bool forSelectionPreservation = false;
+ TextIteratorBehaviors behaviors;
+#if USE(ATSPI)
+ behaviors.add(TextIteratorBehavior::EmitsObjectReplacementCharacters);
+#elif USE(ATK)
+ behaviors.add(TextIteratorBehavior::EmitsCharactersBetweenAllVisiblePositions);
#endif
- return WebCore::indexForVisiblePosition(*node, position, forSelectionPreservation);
+ return WebCore::indexForVisiblePosition(*node, position, behaviors);
}
Element* AccessibilityRenderObject::rootEditableElementForPosition(const Position& position) const
Modified: trunk/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp (285338 => 285339)
--- trunk/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp 2021-11-05 08:21:13 UTC (rev 285338)
+++ trunk/Source/WebCore/accessibility/atspi/AccessibilityObjectTextAtspi.cpp 2021-11-05 08:22:39 UTC (rev 285339)
@@ -610,9 +610,9 @@
auto rangeInParent = *makeSimpleRange(parentFirstPosition, nodeRangeStart);
// Set values for start offsets and calculate initial range length.
- int startOffset = characterCount(rangeInParent, TextIteratorBehavior::EmitsCharactersBetweenAllVisiblePositions);
+ int startOffset = characterCount(rangeInParent, TextIteratorBehavior::EmitsObjectReplacementCharacters);
auto nodeRange = *makeSimpleRange(nodeRangeStart, nodeRangeEnd);
- int rangeLength = characterCount(nodeRange, TextIteratorBehavior::EmitsCharactersBetweenAllVisiblePositions);
+ int rangeLength = characterCount(nodeRange, TextIteratorBehavior::EmitsObjectReplacementCharacters);
return { startOffset, startOffset + rangeLength };
}
Modified: trunk/Source/WebCore/editing/Editing.cpp (285338 => 285339)
--- trunk/Source/WebCore/editing/Editing.cpp 2021-11-05 08:21:13 UTC (rev 285338)
+++ trunk/Source/WebCore/editing/Editing.cpp 2021-11-05 08:22:39 UTC (rev 285339)
@@ -994,15 +994,12 @@
}
// FIXME: Merge this function with the one above.
-int indexForVisiblePosition(Node& node, const VisiblePosition& visiblePosition, bool forSelectionPreservation)
+int indexForVisiblePosition(Node& node, const VisiblePosition& visiblePosition, TextIteratorBehaviors behaviors)
{
if (visiblePosition.isNull())
return 0;
auto range = makeSimpleRange(makeBoundaryPointBeforeNodeContents(node), visiblePosition);
- TextIteratorBehaviors behaviors;
- if (forSelectionPreservation)
- behaviors.add(TextIteratorBehavior::EmitsCharactersBetweenAllVisiblePositions);
return range ? characterCount(*range, behaviors) : 0;
}
@@ -1016,11 +1013,11 @@
return visiblePositionForIndex(startIndex + offset, root.get());
}
-VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope)
+VisiblePosition visiblePositionForIndex(int index, Node* scope, TextIteratorBehaviors behaviors)
{
if (!scope)
return { };
- return { makeDeprecatedLegacyPosition(resolveCharacterLocation(makeRangeSelectingNodeContents(*scope), index, TextIteratorBehavior::EmitsCharactersBetweenAllVisiblePositions)) };
+ return { makeDeprecatedLegacyPosition(resolveCharacterLocation(makeRangeSelectingNodeContents(*scope), index, behaviors)) };
}
VisiblePosition visiblePositionForIndexUsingCharacterIterator(Node& node, int index)
Modified: trunk/Source/WebCore/editing/Editing.h (285338 => 285339)
--- trunk/Source/WebCore/editing/Editing.h 2021-11-05 08:21:13 UTC (rev 285338)
+++ trunk/Source/WebCore/editing/Editing.h 2021-11-05 08:22:39 UTC (rev 285339)
@@ -26,6 +26,7 @@
#pragma once
#include "Position.h"
+#include "TextIteratorBehavior.h"
#include <wtf/Forward.h>
#include <wtf/HashSet.h>
#include <wtf/unicode/CharacterNames.h>
@@ -144,9 +145,9 @@
bool lineBreakExistsAtVisiblePosition(const VisiblePosition&);
WEBCORE_EXPORT int indexForVisiblePosition(const VisiblePosition&, RefPtr<ContainerNode>& scope);
-int indexForVisiblePosition(Node&, const VisiblePosition&, bool forSelectionPreservation);
+int indexForVisiblePosition(Node&, const VisiblePosition&, TextIteratorBehaviors);
WEBCORE_EXPORT VisiblePosition visiblePositionForPositionWithOffset(const VisiblePosition&, int offset);
-WEBCORE_EXPORT VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope);
+WEBCORE_EXPORT VisiblePosition visiblePositionForIndex(int index, Node* scope, TextIteratorBehaviors = TextIteratorBehavior::EmitsCharactersBetweenAllVisiblePositions);
VisiblePosition visiblePositionForIndexUsingCharacterIterator(Node&, int index); // FIXME: Why do we need this version?
WEBCORE_EXPORT VisiblePosition closestEditablePositionInElementForAbsolutePoint(const Element&, const IntPoint&);
Modified: trunk/Tools/ChangeLog (285338 => 285339)
--- trunk/Tools/ChangeLog 2021-11-05 08:21:13 UTC (rev 285338)
+++ trunk/Tools/ChangeLog 2021-11-05 08:22:39 UTC (rev 285339)
@@ -1,3 +1,16 @@
+2021-11-05 Carlos Garcia Campos <[email protected]>
+
+ [GTK][a11y] Embedded objects are not correctly handled by text interface with ATSPI
+ https://bugs.webkit.org/show_bug.cgi?id=232622
+
+ Reviewed by Andres Gonzalez.
+
+ Add a test case to check handling of embedded objects by text interface.
+
+ * TestWebKitAPI/Tests/WebKitGtk/TestWebKitAccessibility.cpp:
+ (testTextReplacedObjects):
+ (beforeAll):
+
2021-11-03 Jonathan Bedard <[email protected]>
[git-webkit] Add land command
Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitGtk/TestWebKitAccessibility.cpp (285338 => 285339)
--- trunk/Tools/TestWebKitAPI/Tests/WebKitGtk/TestWebKitAccessibility.cpp 2021-11-05 08:21:13 UTC (rev 285338)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitGtk/TestWebKitAccessibility.cpp 2021-11-05 08:22:39 UTC (rev 285339)
@@ -1523,6 +1523,97 @@
#endif
}
+static void testTextReplacedObjects(AccessibilityTest* test, gconstpointer)
+{
+#if !USE(ATSPI)
+ g_test_skip("Embedded objects are not correctly handled with ATK");
+#else
+ test->showInWindow(800, 600);
+ test->loadHtml(
+ "<html>"
+ " <body>"
+ " <p>This is <button>button1</button> and <button>button2</button> in paragraph</p>"
+ " </body>"
+ "</html>",
+ nullptr);
+ test->waitUntilLoadFinished();
+
+ auto testApp = test->findTestApplication();
+ g_assert_true(ATSPI_IS_ACCESSIBLE(testApp.get()));
+
+ auto documentWeb = test->findDocumentWeb(testApp.get());
+ g_assert_true(ATSPI_IS_ACCESSIBLE(documentWeb.get()));
+ g_assert_cmpint(atspi_accessible_get_child_count(documentWeb.get(), nullptr), ==, 1);
+
+ auto p = adoptGRef(atspi_accessible_get_child_at_index(documentWeb.get(), 0, nullptr));
+ g_assert_true(ATSPI_IS_TEXT(p.get()));
+ auto length = atspi_text_get_character_count(ATSPI_TEXT(p.get()), nullptr);
+ g_assert_cmpint(length, ==, 28);
+ GUniquePtr<char> text(atspi_text_get_text(ATSPI_TEXT(p.get()), 0, -1, nullptr));
+ g_assert_cmpstr(text.get(), ==, "This is \357\277\274 and \357\277\274 in paragraph");
+ g_assert_cmpint(atspi_accessible_get_child_count(p.get(), nullptr), ==, 2);
+
+ auto button1 = adoptGRef(atspi_accessible_get_child_at_index(p.get(), 0, nullptr));
+ g_assert_true(ATSPI_IS_ACCESSIBLE(button1.get()));
+ text.reset(atspi_accessible_get_name(button1.get(), nullptr));
+ g_assert_cmpstr(text.get(), ==, "button1");
+
+ auto button2 = adoptGRef(atspi_accessible_get_child_at_index(p.get(), 1, nullptr));
+ g_assert_true(ATSPI_IS_ACCESSIBLE(button2.get()));
+ text.reset(atspi_accessible_get_name(button2.get(), nullptr));
+ g_assert_cmpstr(text.get(), ==, "button2");
+
+ UniqueAtspiTextRange range(atspi_text_get_string_at_offset(ATSPI_TEXT(p.get()), 8, ATSPI_TEXT_GRANULARITY_CHAR, nullptr));
+ g_assert_cmpstr(range->content, ==, "\357\277\274");
+ g_assert_cmpint(range->start_offset, ==, 8);
+ g_assert_cmpint(range->end_offset, ==, 9);
+ range.reset(atspi_text_get_string_at_offset(ATSPI_TEXT(p.get()), 14, ATSPI_TEXT_GRANULARITY_CHAR, nullptr));
+ g_assert_cmpstr(range->content, ==, "\357\277\274");
+ g_assert_cmpint(range->start_offset, ==, 14);
+ g_assert_cmpint(range->end_offset, ==, 15);
+
+ range.reset(atspi_text_get_string_at_offset(ATSPI_TEXT(p.get()), 8, ATSPI_TEXT_GRANULARITY_WORD, nullptr));
+ g_assert_cmpstr(range->content, ==, "\357\277\274 ");
+ g_assert_cmpint(range->start_offset, ==, 8);
+ g_assert_cmpint(range->end_offset, ==, 10);
+ range.reset(atspi_text_get_string_at_offset(ATSPI_TEXT(p.get()), 14, ATSPI_TEXT_GRANULARITY_WORD, nullptr));
+ g_assert_cmpstr(range->content, ==, "\357\277\274 ");
+ g_assert_cmpint(range->start_offset, ==, 14);
+ g_assert_cmpint(range->end_offset, ==, 16);
+
+ int startOffset, endOffset;
+ GRefPtr<GHashTable> attributes = adoptGRef(atspi_text_get_attribute_run(ATSPI_TEXT(p.get()), 0, FALSE, &startOffset, &endOffset, nullptr));
+ g_assert_nonnull(attributes.get());
+ g_assert_cmpuint(g_hash_table_size(attributes.get()), ==, 0);
+ g_assert_cmpint(startOffset, ==, 0);
+ g_assert_cmpint(endOffset, ==, 8);
+
+ attributes = adoptGRef(atspi_text_get_attribute_run(ATSPI_TEXT(p.get()), 9, FALSE, &startOffset, &endOffset, nullptr));
+ g_assert_nonnull(attributes.get());
+ g_assert_cmpuint(g_hash_table_size(attributes.get()), >, 0);
+ g_assert_cmpint(startOffset, ==, 8);
+ g_assert_cmpint(endOffset, ==, 9);
+
+ attributes = adoptGRef(atspi_text_get_attribute_run(ATSPI_TEXT(p.get()), 11, FALSE, &startOffset, &endOffset, nullptr));
+ g_assert_nonnull(attributes.get());
+ g_assert_cmpuint(g_hash_table_size(attributes.get()), ==, 0);
+ g_assert_cmpint(startOffset, ==, 9);
+ g_assert_cmpint(endOffset, ==, 14);
+
+ attributes = adoptGRef(atspi_text_get_attribute_run(ATSPI_TEXT(p.get()), 15, FALSE, &startOffset, &endOffset, nullptr));
+ g_assert_nonnull(attributes.get());
+ g_assert_cmpuint(g_hash_table_size(attributes.get()), >, 0);
+ g_assert_cmpint(startOffset, ==, 14);
+ g_assert_cmpint(endOffset, ==, 15);
+
+ attributes = adoptGRef(atspi_text_get_attribute_run(ATSPI_TEXT(p.get()), 18, FALSE, &startOffset, &endOffset, nullptr));
+ g_assert_nonnull(attributes.get());
+ g_assert_cmpuint(g_hash_table_size(attributes.get()), ==, 0);
+ g_assert_cmpint(startOffset, ==, 15);
+ g_assert_cmpint(endOffset, ==, 28);
+#endif
+}
+
void beforeAll()
{
AccessibilityTest::add("WebKitAccessibility", "accessible/basic-hierarchy", testAccessibleBasicHierarchy);
@@ -1542,6 +1633,7 @@
AccessibilityTest::add("WebKitAccessibility", "text/selections", testTextSelections);
AccessibilityTest::add("WebKitAccessibility", "text/attributes", testTextAttributes);
AccessibilityTest::add("WebKitAccessibility", "text/state-changed", testTextStateChanged);
+ AccessibilityTest::add("WebKitAccessibility", "text/replaced-objects", testTextReplacedObjects);
}
void afterAll()
_______________________________________________ webkit-changes mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-changes
