diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift index 57fa56e77..a47dbdaca 100644 --- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift +++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift @@ -1921,6 +1921,59 @@ extension Ghostty.SurfaceView { let str = String(cString: text.text) return str.isEmpty ? nil : str } + + /// Returns the number of characters in the terminal content. + /// This helps assistive technologies understand the size of the content. + override func accessibilityNumberOfCharacters() -> Int { + let content = cachedScreenContents.get() + return content.count + } + + /// Returns the visible character range for the terminal. + /// For terminals, we typically show all content as visible. + override func accessibilityVisibleCharacterRange() -> NSRange { + let content = cachedScreenContents.get() + return NSRange(location: 0, length: content.count) + } + + /// Returns the line number for a given character index. + /// This helps assistive technologies navigate by line. + override func accessibilityLine(for index: Int) -> Int { + let content = cachedScreenContents.get() + let substring = String(content.prefix(index)) + return substring.components(separatedBy: .newlines).count - 1 + } + + /// Returns a substring for the given range. + /// This allows assistive technologies to read specific portions of the content. + override func accessibilityString(for range: NSRange) -> String? { + let content = cachedScreenContents.get() + guard let swiftRange = Range(range, in: content) else { return nil } + return String(content[swiftRange]) + } + + /// Returns an attributed string for the given range. + /// + /// Note: right now this only applies font information. One day it'd be nice to extend + /// this to copy styling information as well but we need to augment Ghostty core to + /// expose that. + /// + /// This provides styling information to assistive technologies. + override func accessibilityAttributedString(for range: NSRange) -> NSAttributedString? { + guard let surface = self.surface else { return nil } + guard let plainString = accessibilityString(for: range) else { return nil } + + var attributes: [NSAttributedString.Key: Any] = [:] + + // Try to get the font from the surface + if let fontRaw = ghostty_surface_quicklook_font(surface) { + let font = Unmanaged.fromOpaque(fontRaw) + attributes[.font] = font.takeUnretainedValue() + font.release() + } + + return NSAttributedString(string: plainString, attributes: attributes) + } } /// Caches a value for some period of time, evicting it automatically when that time expires.