diff --git a/Sources/Fluid/Services/TypingService.swift b/Sources/Fluid/Services/TypingService.swift index 6cacc699a..b3315b7a8 100644 --- a/Sources/Fluid/Services/TypingService.swift +++ b/Sources/Fluid/Services/TypingService.swift @@ -255,6 +255,13 @@ final class TypingService { return nil } + /// Activation options used to restore focus to the external target app after dictation. + /// `.activateAllWindows` is intentionally omitted: raising every window of a multi-window + /// app (e.g. WebStorm) destroys the user's window layout on each dictation (issue #748). + static let focusRestoreActivationOptions: NSApplication.ActivationOptions = [ + .activateIgnoringOtherApps, + ] + /// Best-effort: activates the app with the given PID, unless it's Fluid itself. @discardableResult static func activateApp(pid: pid_t) -> Bool { @@ -269,7 +276,7 @@ final class TypingService { return false } - return app.activate(options: [.activateAllWindows, .activateIgnoringOtherApps]) + return app.activate(options: Self.focusRestoreActivationOptions) } // MARK: - Public API diff --git a/Tests/FluidDictationIntegrationTests/TypingServiceTransientPasteboardTests.swift b/Tests/FluidDictationIntegrationTests/TypingServiceTransientPasteboardTests.swift index 32276672e..aeedc61ef 100644 --- a/Tests/FluidDictationIntegrationTests/TypingServiceTransientPasteboardTests.swift +++ b/Tests/FluidDictationIntegrationTests/TypingServiceTransientPasteboardTests.swift @@ -63,4 +63,20 @@ final class TypingServiceTransientPasteboardTests: XCTestCase { "ConcealedType signals sensitive content and must not be applied to a transcript" ) } + + func testFocusRestoreDoesNotRaiseAllWindowsOfTargetApp() { + // Issue #748: restoring focus after dictation must NOT raise every window of the + // target app. `.activateAllWindows` brings forward all windows of the process and + // destroys a multi-window layout (e.g. WebStorm) on every dictation. + let options = TypingService.focusRestoreActivationOptions + + XCTAssertTrue( + options.contains(.activateIgnoringOtherApps), + "focus restore must still activate the target app and bring it forward" + ) + XCTAssertFalse( + options.contains(.activateAllWindows), + "Restoring focus must not raise every window of the target app (issue #748)" + ) + } }