Commit 53fa5eef authored by Julie Jeongeun Kim's avatar Julie Jeongeun Kim Committed by Commit Bot

[a11y] Implement support for atk_text_get_offset_at_point()

This CL implements GetOffsetAtPoint which returns the offset of the
character located at the position and adds the unittest for the API.

AX-Relnotes: It supports atk_text_get_offset_at_point() on Linux.
Bug: 1070742
Change-Id: Iff075f3e4f95cc746b67819b9426300c250ff485
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2280805
Commit-Queue: Julie Kim <jkim@igalia.com>
Reviewed-by: default avatarMartin Robinson <mrobinson@igalia.com>
Cr-Commit-Position: refs/heads/master@{#785740}
parent 916bc13e
......@@ -763,4 +763,59 @@ TEST_F(BrowserAccessibilityAuraLinuxTest, TextAtkStaticTextChange) {
EXPECT_STREQ(base::UTF16ToUTF8(div_node->GetHypertext()).c_str(), "Text2");
}
TEST_F(BrowserAccessibilityAuraLinuxTest, TestAtkTextGetOffesetAtPoint) {
ui::AXNodeData static_text1;
static_text1.id = 1;
static_text1.role = ax::mojom::Role::kStaticText;
static_text1.SetName("Hello");
static_text1.child_ids = {2};
ui::AXNodeData inline_box1;
inline_box1.id = 2;
inline_box1.role = ax::mojom::Role::kInlineTextBox;
inline_box1.SetName("Hello");
inline_box1.relative_bounds.bounds = gfx::RectF(0, 50, 25, 30);
std::vector<int32_t> character_offsets1;
// The width of each character is 5px.
character_offsets1.push_back(5);
character_offsets1.push_back(10);
character_offsets1.push_back(15);
character_offsets1.push_back(20);
character_offsets1.push_back(25);
inline_box1.AddIntListAttribute(
ax::mojom::IntListAttribute::kCharacterOffsets, character_offsets1);
inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordStarts,
std::vector<int32_t>{0});
inline_box1.AddIntListAttribute(ax::mojom::IntListAttribute::kWordEnds,
std::vector<int32_t>{5});
std::unique_ptr<BrowserAccessibilityManager> manager(
BrowserAccessibilityManager::Create(
MakeAXTreeUpdate(static_text1, inline_box1),
test_browser_accessibility_delegate_.get()));
ASSERT_NE(nullptr, manager->GetRoot());
BrowserAccessibilityAuraLinux* ax_root =
ToBrowserAccessibilityAuraLinux(manager->GetRoot());
ASSERT_NE(nullptr, ax_root);
AtkObject* root_atk_object = ax_root->GetNode()->GetNativeViewAccessible();
g_object_ref(root_atk_object);
AtkText* atk_text = ATK_TEXT(root_atk_object);
ASSERT_TRUE(ATK_IS_TEXT(atk_text));
int x, y, width, height;
char* text = atk_text_get_text(atk_text, 0, -1);
int root_text_length = g_utf8_strlen(text, -1);
g_free(text);
for (int offset = 0; offset < root_text_length; offset++) {
atk_text_get_character_extents(atk_text, offset, &x, &y, &width, &height,
ATK_XY_SCREEN);
int result = atk_text_get_offset_at_point(atk_text, x, y, ATK_XY_SCREEN);
ASSERT_EQ(offset, result);
}
g_object_unref(root_atk_object);
manager.reset();
}
} // namespace content
......@@ -1024,6 +1024,18 @@ gunichar GetCharacterAtOffset(AtkText* atk_text, int offset) {
return code_point;
}
gint GetOffsetAtPoint(AtkText* text, gint x, gint y, AtkCoordType coords) {
g_return_val_if_fail(ATK_IS_TEXT(text), -1);
AtkObject* atk_object = ATK_OBJECT(text);
AXPlatformNodeAuraLinux* obj =
AXPlatformNodeAuraLinux::FromAtkObject(atk_object);
if (!obj)
return -1;
return obj->GetTextOffsetAtPoint(x, y, coords);
}
// This function returns a single character as a UTF-8 encoded C string because
// the character may be encoded into more than one byte.
char* GetCharacter(AtkText* atk_text,
......@@ -1447,6 +1459,7 @@ void Init(AtkTextIface* iface) {
iface->get_text = GetText;
iface->get_character_count = GetCharacterCount;
iface->get_character_at_offset = GetCharacterAtOffset;
iface->get_offset_at_point = GetOffsetAtPoint;
iface->get_text_after_offset = GetTextAfterOffset;
iface->get_text_before_offset = GetTextBeforeOffset;
iface->get_text_at_offset = GetTextAtOffset;
......@@ -4115,6 +4128,28 @@ size_t AXPlatformNodeAuraLinux::UnicodeToUTF16OffsetInText(int unicode_offset) {
return utf16_offset;
}
int AXPlatformNodeAuraLinux::GetTextOffsetAtPoint(int x,
int y,
AtkCoordType atk_coord_type) {
if (!GetExtentsRelativeToAtkCoordinateType(atk_coord_type).Contains(x, y))
return -1;
AtkObject* atk_object = GetOrCreateAtkObject();
if (!atk_object)
return -1;
int count = atk_text::GetCharacterCount(ATK_TEXT(atk_object));
for (int i = 0; i < count; i++) {
int out_x, out_y, out_width, out_height;
atk_text::GetCharacterExtents(ATK_TEXT(atk_object), i, &out_x, &out_y,
&out_width, &out_height, atk_coord_type);
gfx::Rect rect(out_x, out_y, out_width, out_height);
if (rect.Contains(x, y))
return i;
}
return -1;
}
gfx::Vector2d AXPlatformNodeAuraLinux::GetParentOriginInScreenCoordinates()
const {
AtkObject* parent = GetParent();
......
......@@ -245,6 +245,7 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
const base::OffsetAdjuster::Adjustments& GetHypertextAdjustments();
size_t UTF16ToUnicodeOffsetInText(size_t utf16_offset);
size_t UnicodeToUTF16OffsetInText(int unicode_offset);
int GetTextOffsetAtPoint(int x, int y, AtkCoordType atk_coord_type);
// Called on a toplevel frame to set the document parent, which is the parent
// of the toplevel document. This is used to properly express the ATK embeds
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment