diff --git a/Cotabby/Support/Focus/Applications/BrowserAppDetector.swift b/Cotabby/Support/Focus/Applications/BrowserAppDetector.swift index 96c4d875..fe9c5fbe 100644 --- a/Cotabby/Support/Focus/Applications/BrowserAppDetector.swift +++ b/Cotabby/Support/Focus/Applications/BrowserAppDetector.swift @@ -46,6 +46,14 @@ nonisolated enum BrowserAppDetector { /// editor, the Copilot chat, or the integrated terminal, so no suggestions appear anywhere in the /// app even though screenshot-based OCR keeps working. /// + /// Obsidian (`md.obsidian`, issue #791) is the same failure in a different editor. Its + /// CodeMirror 6 surface is a `contenteditable` with `role="textbox"`, which Chromium exposes as + /// `AXTextArea` only once the web-AX tree is awake. A read-only probe of Obsidian 1.12.7 + /// (Electron 39) showed the application element advertising `AXManualAccessibility` (settable, + /// value 0) while the focused window held a single bare `AXGroup`: the dormant renderer view. + /// With the bundle absent here nothing ever flipped that switch, so the system-wide focus query + /// returned nil and the tracker reported "No focused Accessibility element" on every tick. + /// /// Cursor is intentionally absent: it ships under opaque ToDesktop bundle ids /// (`com.todesktop.`) that change between builds, so there is no stable id to allowlist /// here without a broad `com.todesktop.` prefix that would also prime unrelated ToDesktop apps. @@ -53,7 +61,8 @@ nonisolated enum BrowserAppDetector { "com.clickup.desktop-app", "com.microsoft.vscode", // Visual Studio Code "com.microsoft.vscodeinsiders", // VS Code - Insiders - "com.vscodium" // VSCodium (FOSS VS Code build) + "com.vscodium", // VSCodium (FOSS VS Code build) + "md.obsidian" // Obsidian (Electron, CodeMirror 6 editor) — #791 ] /// Broad check: is the user typing inside any web browser? Used for prompt tone hints. diff --git a/CotabbyTests/Support/Accessibility/WebContentFieldDetectorTests.swift b/CotabbyTests/Support/Accessibility/WebContentFieldDetectorTests.swift index 73e9a2bd..3cb6e067 100644 --- a/CotabbyTests/Support/Accessibility/WebContentFieldDetectorTests.swift +++ b/CotabbyTests/Support/Accessibility/WebContentFieldDetectorTests.swift @@ -66,6 +66,14 @@ final class WebContentFieldDetectorTests: XCTestCase { vendsDOMAttributes: false ) ) + // Obsidian is an allowlisted Electron editor (#791), so its fields count as web content even + // before the DOM-reflection attributes arrive on the focused node. + XCTAssertTrue( + WebContentFieldDetector.isWebContentField( + bundleIdentifier: "md.obsidian", + vendsDOMAttributes: false + ) + ) } func test_nativeAppIsNotWebContent() { diff --git a/CotabbyTests/Support/Focus/Applications/BrowserAppDetectorTests.swift b/CotabbyTests/Support/Focus/Applications/BrowserAppDetectorTests.swift index 4b490178..34074a11 100644 --- a/CotabbyTests/Support/Focus/Applications/BrowserAppDetectorTests.swift +++ b/CotabbyTests/Support/Focus/Applications/BrowserAppDetectorTests.swift @@ -37,6 +37,11 @@ final class BrowserAppDetectorTests: XCTestCase { XCTAssertTrue(BrowserAppDetector.isElectronEditor(bundleIdentifier: "com.microsoft.VSCode")) XCTAssertTrue(BrowserAppDetector.isElectronEditor(bundleIdentifier: "com.microsoft.VSCodeInsiders")) XCTAssertTrue(BrowserAppDetector.isElectronEditor(bundleIdentifier: "com.vscodium")) + // Obsidian (#791): Electron 39 / CodeMirror 6. Its app element advertises + // AXManualAccessibility, but nothing flips it unless the bundle is allowlisted here, so the + // editor's web-AX tree stays dormant and no focused field ever resolves. + XCTAssertTrue(BrowserAppDetector.isElectronEditor(bundleIdentifier: "md.obsidian")) + XCTAssertTrue(BrowserAppDetector.isElectronEditor(bundleIdentifier: "MD.Obsidian")) // Electron, but not a text-editing surface we cover: must stay out of the priming allowlist. XCTAssertFalse(BrowserAppDetector.isElectronEditor(bundleIdentifier: "com.hnc.Discord")) XCTAssertFalse(BrowserAppDetector.isElectronEditor(bundleIdentifier: nil)) @@ -49,6 +54,8 @@ final class BrowserAppDetectorTests: XCTestCase { BrowserAppDetector.needsWebAccessibilityPriming(bundleIdentifier: "com.clickup.desktop-app")) XCTAssertTrue( BrowserAppDetector.needsWebAccessibilityPriming(bundleIdentifier: "com.microsoft.VSCode")) + XCTAssertTrue( + BrowserAppDetector.needsWebAccessibilityPriming(bundleIdentifier: "md.obsidian")) XCTAssertFalse( BrowserAppDetector.needsWebAccessibilityPriming(bundleIdentifier: "com.apple.Safari")) XCTAssertFalse(