fix(review): NameOwnerChanged 支持自定义组合键 + 总是覆盖旧版插件
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) <noreply@anthropic.com>
This commit is contained in:
1 parent
c4cb3c9ee5
commit
163327e17b
2 files changed
+29
-43
No files matched your search
@@ -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<Inner>) {
|
||||
#[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<Inner>) -> Option<String> {
|
||||
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<Inner>) {
|
||||
let prefs = inner.prefs.get();
|
||||
let dictation = &prefs.dictation_hotkey;
|
||||
|
||||
@@ -260,6 +260,7 @@ pub fn start_dictation_signal_listener(
|
||||
binding: crate::types::HotkeyBinding,
|
||||
qa_trigger: Option<crate::types::HotkeyTrigger>,
|
||||
translation_trigger: Option<crate::types::HotkeyTrigger>,
|
||||
custom_trigger_key: Option<String>,
|
||||
) {
|
||||
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 模块已加载)。
|
||||
|
||||
Reference in new issue
Block a user