Merge pull request #633 from Open-Less/fix/issue-631-capsule-click-guard
fix(capsule): 终态/空闲让胶囊点击穿透,修复贴近输入框误触弹主界面 (#631)
This commit is contained in:
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 完全一致:
|
||||
|
||||
Reference in new issue
Block a user