77 lines
2.2 KiB
Go
77 lines
2.2 KiB
Go
// Copyright (c) 2026 Storm Dragon
|
|
// Authors: Storm Dragon, Angus Kola
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
package atspi
|
|
|
|
/*
|
|
#include <atspi/atspi.h>
|
|
*/
|
|
import "C"
|
|
|
|
import "context"
|
|
|
|
// Capture only single-character embedded children. Chromium's ordinary text
|
|
// descendants share their parent's offset domain and need no extra ranges.
|
|
// Require every child to occupy one placeholder, avoiding duplicate text from
|
|
// containers which also expose their plain text through static children.
|
|
// All handles stay on the GLib owner and are released before returning.
|
|
func nativeTextChildren(ctx context.Context, source *C.AtspiAccessible, count int, children []ObjectID) []TextChild {
|
|
if count <= 0 || len(children) == 0 {
|
|
return nil
|
|
}
|
|
hypertext := C.atspi_accessible_get_hypertext_iface(source)
|
|
if hypertext == nil {
|
|
return nil
|
|
}
|
|
defer C.g_object_unref(C.gpointer(hypertext))
|
|
links := int(C.atspi_hypertext_get_n_links(hypertext, nil))
|
|
if links <= 0 || links != len(children) {
|
|
return nil
|
|
}
|
|
text := C.atspi_accessible_get_text_iface(source)
|
|
if text == nil {
|
|
return nil
|
|
}
|
|
defer C.g_object_unref(C.gpointer(text))
|
|
known := make(map[ObjectID]bool, len(children))
|
|
for _, child := range children {
|
|
known[child] = true
|
|
}
|
|
var result []TextChild
|
|
previous := -1
|
|
for index := 0; index < links; index++ {
|
|
if ctx.Err() != nil {
|
|
return nil
|
|
}
|
|
link := C.atspi_hypertext_get_link(hypertext, C.gint(index), nil)
|
|
if link == nil {
|
|
return nil
|
|
}
|
|
start := int(C.atspi_hyperlink_get_start_index(link, nil))
|
|
end := int(C.atspi_hyperlink_get_end_index(link, nil))
|
|
child := C.atspi_hyperlink_get_object(link, 0, nil)
|
|
var id ObjectID
|
|
if child != nil {
|
|
id = nativeObjectID(child)
|
|
C.g_object_unref(C.gpointer(child))
|
|
}
|
|
C.g_object_unref(C.gpointer(link))
|
|
if start <= previous || end != start+1 || start < 0 || end > count || !known[id] {
|
|
return nil
|
|
}
|
|
value := C.atspi_text_get_text(text, C.gint(start), C.gint(end), nil)
|
|
placeholder := value != nil && C.GoString(value) == "\ufffc"
|
|
if value != nil {
|
|
C.g_free(C.gpointer(value))
|
|
}
|
|
if !placeholder {
|
|
return nil
|
|
}
|
|
delete(known, id)
|
|
result = append(result, TextChild{Offset: start, Child: id})
|
|
previous = start
|
|
}
|
|
return result
|
|
}
|