package app import ( "strings" "unicode/utf8" "git.stormux.org/storm/cthulhu/internal/atspi" "git.stormux.org/storm/cthulhu/internal/braille" "git.stormux.org/storm/cthulhu/internal/config" ) // Python includes context at the first line of text areas and omits desktop // ancestry within web documents. Verbosity changes roles, not group labels. func braille_context_frame(frame braille.Frame, snapshot atspi.Snapshot, options config.BrailleOptions) braille.Frame { if snapshot.Role == "terminal" || snapshot.TextCaretKnown && snapshot.BrailleLineStart > 0 { return frame } for _, ancestor := range snapshot.BrailleContext { if atspi.IsWebDocumentRole(ancestor.Role) { return frame } } parts := []string{} groupSkipped := false ancestors := snapshot.BrailleContext if len(ancestors) > 0 { switch ancestors[0].Role { case "menu", "menu bar", "page tab list", "redundant object", "unknown", "combo box": ancestors = ancestors[1:] } } for index := len(ancestors) - 1; index >= 0; index-- { ancestor := ancestors[index] if ancestor.ID().Valid() && ancestor.ID() == snapshot.ID() { continue } switch ancestor.Role { case "invalid", "unknown", "redundant object", "section", "split pane", "desktop frame", "scroll pane", "viewport": continue case "panel", "filler", "grouping": if strings.TrimSpace(ancestor.Name) == "" { continue } if snapshot.Role == "radio button" && ancestor.Name == snapshot.RadioGroupName && !groupSkipped { groupSkipped = true continue } } if ancestor.Role == "table" && ancestor.LayoutTable { continue } text := braille_object_frame(ancestor, options).Text if text != "" { parts = append(parts, text) } } parts = append(parts, snapshot.TableRowHeaders, snapshot.TableColumnHeaders, snapshot.RadioGroupName) prefix := brailleJoin(parts...) if prefix == "" { return frame } prefix += " " shift := utf8.RuneCountInString(prefix) frame.Text = prefix + frame.Text if frame.Cursor >= 0 { frame.Cursor += shift } if len(frame.Dots) != 0 { frame.Dots = append(make([]byte, shift), frame.Dots...) } for index := range frame.Routes { frame.Routes[index].Start += shift frame.Routes[index].End += shift } return frame }