Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions openless-all/app/src-tauri/src/coordinator/capsule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 加的
Expand Down
13 changes: 13 additions & 0 deletions openless-all/app/src-tauri/src/coordinator/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 完全一致:
Expand Down
Loading