From 163327e17b96160bceea85ac39a6926d8943de60 Mon Sep 17 00:00:00 2001 From: aeoform <2790848120@qq.com> Date: Fri, 22 May 2026 21:20:19 +0800 Subject: [PATCH] =?UTF-8?q?fix(review):=20NameOwnerChanged=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E7=BB=84=E5=90=88=E9=94=AE?= =?UTF-8?q?=20+=20=E6=80=BB=E6=98=AF=E8=A6=86=E7=9B=96=E6=97=A7=E7=89=88?= =?UTF-8?q?=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. start_dictation_signal_listener 新增 custom_trigger_key 参数, NameOwnerChanged 和初始同步都通过 resync_main_binding 分支处理 自定义组合键 vs 预设修饰键 2. ensure_plugin_installed 去掉"已安装即跳过"检查,AppImage 每次启动 都覆盖最新 .so + .conf,确保新 DBus 方法不会因旧插件丢失 Co-Authored-By: Claude Opus 4.7 (1M context) --- openless-all/app/src-tauri/src/coordinator.rs | 15 +++++ openless-all/app/src-tauri/src/linux_fcitx.rs | 57 +++++-------------- 2 files changed, 29 insertions(+), 43 deletions(-) diff --git a/openless-all/app/src-tauri/src/coordinator.rs b/openless-all/app/src-tauri/src/coordinator.rs index afc602f1..b37bbe34 100644 --- a/openless-all/app/src-tauri/src/coordinator.rs +++ b/openless-all/app/src-tauri/src/coordinator.rs @@ -824,11 +824,13 @@ impl Coordinator { #[cfg(target_os = "linux")] { let (qa_trigger, translation_trigger) = modifier_shortcut_triggers(&self.inner); + let custom_key = custom_dictation_key_string(&self.inner); crate::linux_fcitx::start_dictation_signal_listener( fcitx_tx, fcitx_binding.clone(), qa_trigger, translation_trigger, + custom_key, ); if fcitx_binding.trigger == crate::types::HotkeyTrigger::Custom { sync_custom_dictation_to_plugin(&self.inner); @@ -1109,11 +1111,13 @@ fn hotkey_supervisor_loop(inner: Arc) { #[cfg(target_os = "linux")] { let (qa_trigger, translation_trigger) = modifier_shortcut_triggers(&inner); + let custom_key = custom_dictation_key_string(&inner); crate::linux_fcitx::start_dictation_signal_listener( fcitx_tx, fcitx_binding.clone(), qa_trigger, translation_trigger, + custom_key, ); if fcitx_binding.trigger == crate::types::HotkeyTrigger::Custom { sync_custom_dictation_to_plugin(&inner); @@ -1696,6 +1700,17 @@ fn is_builtin_translation_shift(binding: &crate::types::ShortcutBinding) -> bool /// Linux: 从 prefs 读取自定义组合键,同步到 fcitx5 插件。 #[cfg(target_os = "linux")] +#[cfg(target_os = "linux")] +fn custom_dictation_key_string(inner: &Arc) -> Option { + let prefs = inner.prefs.get(); + let key_string = crate::linux_fcitx::binding_to_fcitx_key_string(&prefs.dictation_hotkey); + if key_string.is_empty() { + None + } else { + Some(key_string) + } +} + fn sync_custom_dictation_to_plugin(inner: &Arc) { let prefs = inner.prefs.get(); let dictation = &prefs.dictation_hotkey; diff --git a/openless-all/app/src-tauri/src/linux_fcitx.rs b/openless-all/app/src-tauri/src/linux_fcitx.rs index 9dae5b09..73d6039b 100644 --- a/openless-all/app/src-tauri/src/linux_fcitx.rs +++ b/openless-all/app/src-tauri/src/linux_fcitx.rs @@ -260,6 +260,7 @@ pub fn start_dictation_signal_listener( binding: crate::types::HotkeyBinding, qa_trigger: Option, translation_trigger: Option, + custom_trigger_key: Option, ) { use std::time::Duration; @@ -338,6 +339,7 @@ pub fn start_dictation_signal_listener( }; let binding_for_name = binding.clone(); + let custom_for_name = custom_trigger_key.clone(); let qa_for_name = qa_trigger; let trans_for_name = translation_trigger; let _name_match = match conn.add_match(fcitx_rule, move |args: (String, String, String), _conn, _msg| { @@ -346,7 +348,7 @@ pub fn start_dictation_signal_listener( // fcitx5 已启动(或重启),重新同步所有快捷键绑定。 log::info!("[fcitx-hotkey] fcitx5 appeared on DBus, re-syncing bindings"); std::thread::sleep(Duration::from_secs(1)); // 等插件完全加载 - sync_binding_to_plugin(&binding_for_name); + resync_main_binding(&binding_for_name, custom_for_name.as_deref()); sync_qa_binding(qa_for_name); sync_translation_binding(trans_for_name); } @@ -363,7 +365,7 @@ pub fn start_dictation_signal_listener( for attempt in 0..10 { if fcitx5_name_has_owner(&conn) { log::info!("[fcitx-hotkey] fcitx5 available, syncing initial bindings (attempt {attempt})"); - sync_binding_to_plugin(&binding); + resync_main_binding(&binding, custom_trigger_key.as_deref()); sync_qa_binding(qa_trigger); sync_translation_binding(translation_trigger); break; @@ -394,11 +396,6 @@ pub fn start_dictation_signal_listener( pub fn ensure_plugin_installed(app: &tauri::AppHandle) { use tauri::Manager; - if is_plugin_installed_on_disk() { - log::info!("[fcitx-install] Plugin already installed on disk"); - return; - } - let resource_dir = match app.path().resource_dir() { Ok(d) => d, Err(e) => { @@ -473,44 +470,18 @@ pub fn ensure_plugin_installed(app: &tauri::AppHandle) { ); } -#[cfg(target_os = "linux")] -fn is_plugin_installed_on_disk() -> bool { - // 同时检查 .so 和 .conf:孤立的 .so 没有 addon 配置 fcitx5 也不会加载。 - let pairs: &[(&str, &str)] = &[ - ( - "/usr/lib/x86_64-linux-gnu/fcitx5/libopenless.so", - "/usr/share/fcitx5/addon/openless.conf", - ), - ( - "/usr/lib64/fcitx5/libopenless.so", - "/usr/share/fcitx5/addon/openless.conf", - ), - ( - "/usr/local/lib/fcitx5/libopenless.so", - "/usr/local/share/fcitx5/addon/openless.conf", - ), - ( - "/usr/lib/fcitx5/libopenless.so", - "/usr/share/fcitx5/addon/openless.conf", - ), - ]; - for (so, conf) in pairs { - if std::path::Path::new(so).exists() && std::path::Path::new(conf).exists() { - return true; +/// 同步主听写热键:自定义组合键走 SetCustomDictationTrigger,预设修饰键走 SetHotkeyRaw。 +fn resync_main_binding(binding: &crate::types::HotkeyBinding, custom_trigger_key: Option<&str>) { + if let Some(key_string) = custom_trigger_key { + if !key_string.is_empty() { + match set_custom_dictation_trigger(key_string) { + Ok(()) => log::info!("[fcitx] Resynced custom dictation trigger '{key_string}'"), + Err(e) => log::warn!("[fcitx] Failed to resync custom dictation trigger: {e}"), + } + return; } } - - if let Ok(home) = std::env::var("HOME") { - let user_so = std::path::PathBuf::from(&home) - .join(".local").join("lib").join("fcitx5").join("libopenless.so"); - let user_conf = std::path::PathBuf::from(&home) - .join(".local").join("share").join("fcitx5").join("addon").join("openless.conf"); - if user_so.exists() && user_conf.exists() { - return true; - } - } - - false + sync_binding_to_plugin(binding); } /// 检查 fcitx5 是否在 DBus 上注册了名称(即 fcitx5 进程是否在运行且 DBus 模块已加载)。