Found a few ways in which the Braille problem with browsers could resurface. Fixed now.
This commit is contained in:
1 parent
0a3d946ffa
commit
a47253d697
13 files changed
+292
-23
No files matched your search
@@ -43,6 +43,25 @@ import (
|
||||
type embeddedTextBudget struct {
|
||||
nodes, characters int
|
||||
deadline time.Time
|
||||
incomplete bool
|
||||
}
|
||||
|
||||
// The display text may expand, but every offset continues to describe RawText.
|
||||
// Keep the same bounded expansion and recovery rules for browse reads and
|
||||
// native caret snapshots.
|
||||
func expandNativeDocumentText(ctx context.Context, source *C.AtspiAccessible, snapshot Snapshot, line DocumentCaretText) DocumentCaretText {
|
||||
line.RawText = line.Text
|
||||
if snapshot.Editable || snapshot.Role == "password text" || snapshot.Role == "terminal" || !strings.ContainsRune(line.Text, '\ufffc') {
|
||||
return line
|
||||
}
|
||||
deadline := time.Now().Add(100 * time.Millisecond)
|
||||
if ctxDeadline, ok := ctx.Deadline(); ok && ctxDeadline.Before(deadline) {
|
||||
deadline = ctxDeadline
|
||||
}
|
||||
budget := embeddedTextBudget{nodes: 32, characters: maxSnapshotFieldLength, deadline: deadline}
|
||||
expanded := expandNativeEmbeddedText(source, line.Text, line.Start, 0, &budget)
|
||||
line.applyExpandedText(expanded, snapshot.Name, budget.incomplete)
|
||||
return line
|
||||
}
|
||||
|
||||
func expandNativeEmbeddedText(source *C.AtspiAccessible, content string, start, depth int, budget *embeddedTextBudget) string {
|
||||
@@ -51,6 +70,7 @@ func expandNativeEmbeddedText(source *C.AtspiAccessible, content string, start,
|
||||
for _, char := range content {
|
||||
offset++
|
||||
if budget.characters <= 0 {
|
||||
budget.incomplete = true
|
||||
break
|
||||
}
|
||||
if char != '\ufffc' {
|
||||
@@ -59,6 +79,7 @@ func expandNativeEmbeddedText(source *C.AtspiAccessible, content string, start,
|
||||
continue
|
||||
}
|
||||
if depth >= 8 || budget.nodes <= 0 || time.Now().After(budget.deadline) {
|
||||
budget.incomplete = true
|
||||
continue
|
||||
}
|
||||
budget.nodes--
|
||||
@@ -70,6 +91,7 @@ func expandNativeEmbeddedText(source *C.AtspiAccessible, content string, start,
|
||||
func expandNativeEmbeddedChild(source *C.AtspiAccessible, offset, depth int, budget *embeddedTextBudget) string {
|
||||
hypertext := C.atspi_accessible_get_hypertext_iface(source)
|
||||
if hypertext == nil {
|
||||
budget.incomplete = true
|
||||
return ""
|
||||
}
|
||||
defer C.g_object_unref(C.gpointer(hypertext))
|
||||
@@ -77,18 +99,22 @@ func expandNativeEmbeddedChild(source *C.AtspiAccessible, offset, depth int, bud
|
||||
index := C.atspi_hypertext_get_link_index(hypertext, C.gint(offset), &nativeErr)
|
||||
if nativeErr != nil {
|
||||
C.g_error_free(nativeErr)
|
||||
budget.incomplete = true
|
||||
return ""
|
||||
}
|
||||
if index < 0 {
|
||||
budget.incomplete = true
|
||||
return ""
|
||||
}
|
||||
link := C.atspi_hypertext_get_link(hypertext, index, nil)
|
||||
if link == nil {
|
||||
budget.incomplete = true
|
||||
return ""
|
||||
}
|
||||
defer C.g_object_unref(C.gpointer(link))
|
||||
child := C.atspi_hyperlink_get_object(link, 0, nil)
|
||||
if child == nil {
|
||||
budget.incomplete = true
|
||||
return ""
|
||||
}
|
||||
defer C.g_object_unref(C.gpointer(child))
|
||||
@@ -98,23 +124,34 @@ func expandNativeEmbeddedChild(source *C.AtspiAccessible, offset, depth int, bud
|
||||
}
|
||||
text := C.atspi_accessible_get_text_iface(child)
|
||||
if text == nil {
|
||||
budget.incomplete = true
|
||||
return ""
|
||||
}
|
||||
defer C.g_object_unref(C.gpointer(text))
|
||||
count := C.atspi_text_get_character_count(text, nil)
|
||||
if count <= 0 || time.Now().After(budget.deadline) {
|
||||
budget.incomplete = true
|
||||
return ""
|
||||
}
|
||||
if count > C.gint(maxSnapshotFieldLength) {
|
||||
budget.incomplete = true
|
||||
}
|
||||
content := C.atspi_text_get_text(text, 0, min(count, C.gint(maxSnapshotFieldLength)), nil)
|
||||
if content == nil {
|
||||
budget.incomplete = true
|
||||
return ""
|
||||
}
|
||||
defer C.g_free(C.gpointer(content))
|
||||
length := int(C.review_text_length(content, C.int(maxSnapshotFieldLength*utf8.UTFMax)))
|
||||
if length < 0 || length > maxSnapshotFieldLength*utf8.UTFMax {
|
||||
budget.incomplete = true
|
||||
return ""
|
||||
}
|
||||
expanded := expandNativeEmbeddedText(child, C.GoStringN(content, C.int(length)), 0, depth, budget)
|
||||
value := C.GoStringN(content, C.int(length))
|
||||
if !utf8.ValidString(value) || utf8.RuneCountInString(value) != min(int(count), maxSnapshotFieldLength) {
|
||||
budget.incomplete = true
|
||||
}
|
||||
expanded := expandNativeEmbeddedText(child, value, 0, depth, budget)
|
||||
switch role {
|
||||
case C.ATSPI_ROLE_HEADING, C.ATSPI_ROLE_LIST, C.ATSPI_ROLE_LIST_ITEM, C.ATSPI_ROLE_PARAGRAPH,
|
||||
C.ATSPI_ROLE_SECTION, C.ATSPI_ROLE_TABLE, C.ATSPI_ROLE_TABLE_CELL, C.ATSPI_ROLE_TABLE_ROW:
|
||||
|
||||
Reference in new issue
Block a user