Skip to content

[mic][permissions] 主听写在缺麦克风权限时违反 "不抢前台焦点" 约定 #166

@appergb

Description

@appergb

现象

CLAUDE.md 明确"不要在 dictation 路径上 `NSApp.activate` / `activateIgnoringOtherApps`,会破坏 insertion"——但当用户麦克风权限缺失时,dictation 路径反而主动抢前台焦点:

```
用户在 Notes 写字 → 按 hotkey 录音 → 麦克风权限恰好缺
→ OpenLess 主窗口跳到前台抢走 Notes 的焦点(弹"请授权"对话框)
→ 用户骂街
```

虽然首次缺权限场景才触发,但跳焦的动作很扎眼。

复现

  1. macOS 第一次安装 OpenLess(或手动撤掉 mic 权限)
  2. 在 Notes 编辑文档
  3. 按 rightOption 录音
  4. 观察:OpenLess 主窗口跳到前台、Notes 失焦

根因

coordinator.rs:1472 的 `ensure_microphone_permission`:

```rust
fn ensure_microphone_permission(inner: &Arc) -> Result<(), String> {
// ... 缺权限路径调用:
show_main_window(&app); // ← 这里调 set_dock_visibility(true) + activateIgnoringOtherApps
return Err("缺少麦克风权限".to_string());
}
```

`show_main_window` 在 macOS 上会:
```rust
app.set_activation_policy(Regular); // dock 显
ns_app.activateIgnoringOtherApps(true); // 抢焦点
window.show();
```

CLAUDE.md 明确:

Don't NSApp.activate on the dictation path — it steals focus and breaks insertion.

`ensure_microphone_permission` 是在 `begin_session` 早期被调,属于 dictation path。

影响

  • macOS 第一次缺权限场景(用户首次按 hotkey)
  • 也可能在已撤回权限的场景(用户改隐私设置)
  • 体感:突然跳焦、原 app 状态丢失(当前光标位置 / 输入法状态)

建议 fix

把"缺权限提示" 通路从"抢焦点 show 主窗口"改成"通知中心 + 胶囊":

```rust
// 缺 mic 权限时:
emit_capsule(inner, CapsuleState::Error, 0.0, 0,
Some("需要麦克风权限".into()), None);
// 用户点胶囊 / 等下次按时再去主窗口请求权限(用户主动唤起,不是被强夺)
```

或最低限度:去掉 `activateIgnoringOtherApps(true)`,只 `window.show()` 不抢焦点。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions