Cthulhu is no longer a fork. Now it is a screen reader written in Golang.
This commit is contained in:
1 parent
a998fe67de
commit
069fc674dc
708 files changed
+112482
-532
No files matched your search
@@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.stormux.org/storm/cthulhu/internal/atspi"
|
||||
"git.stormux.org/storm/cthulhu/internal/presentation"
|
||||
)
|
||||
|
||||
func (worker *speechWorker) context_messages(ancestors []atspi.Snapshot) []string {
|
||||
return worker.context_messages_for(ancestors, false)
|
||||
}
|
||||
|
||||
func (worker *speechWorker) context_messages_for(ancestors []atspi.Snapshot, sayAll bool) []string {
|
||||
if ancestors == nil || worker.reading == nil {
|
||||
return nil
|
||||
}
|
||||
current := make([]atspi.Snapshot, 0, len(ancestors))
|
||||
for _, ancestor := range ancestors {
|
||||
if presentation.ContextType(ancestor) != "" {
|
||||
current = append(current, ancestor)
|
||||
}
|
||||
}
|
||||
previous := worker.speechContext
|
||||
worker.speechContext = current
|
||||
settings := worker.reading()
|
||||
contains := func(values []atspi.Snapshot, candidate atspi.Snapshot) bool {
|
||||
for _, item := range values {
|
||||
if item.ID() == candidate.ID() && item.Role == candidate.Role && item.XMLRoles == candidate.XMLRoles {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
var messages []string
|
||||
panelMessages := make(map[string]bool)
|
||||
appendMessage := func(item atspi.Snapshot, message string) {
|
||||
// Keep every container identity for later transitions, but say an
|
||||
// identical panel label only once in this transition.
|
||||
if presentation.ContextType(item) == "panel" {
|
||||
if panelMessages[message] {
|
||||
return
|
||||
}
|
||||
panelMessages[message] = true
|
||||
}
|
||||
messages = append(messages, message)
|
||||
}
|
||||
enabled := presentation.ContextEnabled
|
||||
verbosity := 0
|
||||
if worker.verbosity != nil {
|
||||
verbosity = worker.verbosity()
|
||||
}
|
||||
if sayAll {
|
||||
enabled = presentation.SayAllContextEnabled
|
||||
}
|
||||
for _, item := range previous {
|
||||
if !contains(current, item) && enabled(presentation.ContextType(item), settings) {
|
||||
appendMessage(item, "Leaving "+presentation.ContextLabel(item)+".")
|
||||
}
|
||||
}
|
||||
for index := len(current) - 1; index >= 0; index-- {
|
||||
item := current[index]
|
||||
if !contains(previous, item) && enabled(presentation.ContextType(item), settings) {
|
||||
appendMessage(item, presentation.ContextCountLabel(item, verbosity))
|
||||
}
|
||||
}
|
||||
return messages
|
||||
}
|
||||
|
||||
func (worker *speechWorker) deliver_context(ctx context.Context, request speechRequest) error {
|
||||
return worker.deliver_context_for(ctx, request.Context, false)
|
||||
}
|
||||
|
||||
func (worker *speechWorker) deliver_context_for(ctx context.Context, ancestors []atspi.Snapshot, sayAll bool) error {
|
||||
for _, message := range worker.context_messages_for(ancestors, sayAll) {
|
||||
worker.logDelivery(ctx, speechRequest{Role: "system", Cause: "reading-context", Append: true}, message, -1)
|
||||
if voiced, ok := worker.speaker.(interface {
|
||||
SpeakVoice(context.Context, string, string) error
|
||||
}); ok {
|
||||
if err := voiced.SpeakVoice(ctx, message, "system"); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err := worker.speaker.Speak(ctx, message); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func document_line_voice(line atspi.DocumentLine) string {
|
||||
for _, content := range line.Contents {
|
||||
if content.Snapshot.Role == "link" {
|
||||
return "hyperlink"
|
||||
}
|
||||
}
|
||||
return "default"
|
||||
}
|
||||
|
||||
func ancestor_voice(ancestors []atspi.Snapshot) string {
|
||||
for _, ancestor := range ancestors {
|
||||
if ancestor.Role == "link" {
|
||||
return "hyperlink"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in new issue
Block a user