Merge pull request #633 from Open-Less/fix/issue-631-capsule-click-guard

fix(capsule): 终态/空闲让胶囊点击穿透,修复贴近输入框误触弹主界面 (#631)
This commit is contained in:
Chris233 authored and GitHub committed 2026-06-10 12:14:05 +08:00
commit cffbd06adb
2 files changed
+35

No files matched your search

@@ -29,6 +29,9 @@ pub(crate) fn capsule_show_strategy_for_platform() -> CapsuleShowStrategy {
static CAPSULE_NO_ACTIVATE_FALLBACK_WARNED: AtomicBool = AtomicBool::new(false);
static CAPSULE_SUPPRESSED_BY_TOGGLE_LOGGED: AtomicBool = AtomicBool::new(false);
static CAPSULE_FIRST_SHOW_LOGGED: AtomicBool = AtomicBool::new(false);
// issue #631:上一次应用到胶囊窗口的点击穿透值。初始 false 与窗口创建时一致
// (tauri.conf.json 未设 ignore),按变化去重,避免录音中 ~30Hz 电平帧重复调系统 API。
static CAPSULE_IGNORE_CURSOR_APPLIED: AtomicBool = AtomicBool::new(false);
// #470 诊断 v2:capsule webview 句柄取不到时的一次性门,区分「窗口压根没创建」(A0)。
static CAPSULE_WINDOW_MISSING_LOGGED: AtomicBool = AtomicBool::new(false);
@@ -69,6 +72,18 @@ pub(crate) fn show_capsule_window_for_recording<R: tauri::Runtime>(
}
}
/// issue #631:该状态下胶囊窗口是否应忽略鼠标事件(点击穿透到下层应用)。
/// 胶囊窗口 220×110 远大于可见 pill,贴近输入框时透明区域会吃掉用户点击并激活
/// OpenLess(误触弹出主界面)。终态(Done/Cancelled/Error)与 Idle 没有可交互
/// 按钮——包括 2s toast 停留和离场动画期间——让点击穿透;录音/转写/润色态有
/// ✕/✓ 按钮,保持可点。
pub(crate) fn capsule_ignore_cursor_for_state(state: CapsuleState) -> bool {
!matches!(
state,
CapsuleState::Recording | CapsuleState::Transcribing | CapsuleState::Polishing
)
}
/// 终止态(Done / Cancelled / Error)后延迟 N ms 把胶囊改回 Idle,让浮窗自动消失。
/// 用户点 ✕ / ✓ / 中途出错 / 按 Esc 都走这里,统一 2 秒。
pub(crate) const CAPSULE_AUTO_HIDE_DELAY_MS: u64 = 2000;
@@ -242,6 +257,13 @@ pub(crate) fn emit_capsule(
#[cfg(not(target_os = "linux"))]
{
// issue #631:终态/空闲让胶囊点击穿透,录音完成后用户点击贴近的输入框
// 不再误触胶囊激活 OpenLess。状态变化时才真正调系统 API。
let ignore_cursor = capsule_ignore_cursor_for_state(state);
if CAPSULE_IGNORE_CURSOR_APPLIED.swap(ignore_cursor, Ordering::SeqCst) != ignore_cursor {
let _ = window.set_ignore_cursor_events(ignore_cursor);
}
// 三平台统一:Done / Cancelled / Error 状态保留 ~1.5s toast
// (schedule_capsule_idle 之后会回 Idle 隐藏)。
// Windows 上 linger 的真实问题(截图选中 / 死区 / 拖拽卡顿)由 #140 加的
@@ -810,6 +810,19 @@ fn window_hotkey_fallback_is_disabled_when_no_explicit_fallback_is_advertised()
);
}
#[test]
fn capsule_ignore_cursor_only_in_non_interactive_states() {
// issue #631:有 ✕/✓ 按钮的三个状态必须可点;终态/空闲(含 toast 停留与
// 离场动画期间)点击穿透,避免误触激活 OpenLess 弹出主界面。
assert!(!capsule_ignore_cursor_for_state(CapsuleState::Recording));
assert!(!capsule_ignore_cursor_for_state(CapsuleState::Transcribing));
assert!(!capsule_ignore_cursor_for_state(CapsuleState::Polishing));
assert!(capsule_ignore_cursor_for_state(CapsuleState::Done));
assert!(capsule_ignore_cursor_for_state(CapsuleState::Cancelled));
assert!(capsule_ignore_cursor_for_state(CapsuleState::Error));
assert!(capsule_ignore_cursor_for_state(CapsuleState::Idle));
}
#[test]
fn capsule_show_strategy_matches_platform_activation_contract() {
// 平台列表必须与 capsule_show_strategy_for_platform 的 cfg 完全一致: