fix(app): load host GTK IM modules for AppImage

This commit is contained in:
backtrack 2026-06-26 12:13:41 +08:00 committed by GitHub
parent c3d47ece2c
commit 546a59b1e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 129 additions and 3 deletions

View File

@ -85,6 +85,19 @@ fn linux_webkit_rendering_workarounds() -> &'static [(&'static str, &'static str
]
}
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
fn linux_system_gtk3_immodules_cache_path() -> Option<&'static str> {
[
"/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules.cache",
"/usr/lib/aarch64-linux-gnu/gtk-3.0/3.0.0/immodules.cache",
"/usr/lib64/gtk-3.0/3.0.0/immodules.cache",
"/usr/lib/gtk-3.0/3.0.0/immodules.cache",
]
.iter()
.copied()
.find(|path| std::path::Path::new(path).is_file())
}
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
fn linux_appimage_wayland_backend_override(
appimage: Option<&std::ffi::OsStr>,
@ -101,6 +114,33 @@ fn linux_appimage_wayland_backend_override(
}
}
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
fn linux_appimage_system_gtk_immodules_cache(
appimage: Option<&std::ffi::OsStr>,
appdir: Option<&std::ffi::OsStr>,
gtk_im_module: Option<&std::ffi::OsStr>,
gtk_im_module_file: Option<&std::ffi::OsStr>,
system_cache_path: Option<&'static str>,
) -> Option<&'static str> {
let system_cache_path = system_cache_path?;
if appimage.is_none() || gtk_im_module.is_none() {
return None;
}
let Some(gtk_im_module_file) = gtk_im_module_file else {
return Some(system_cache_path);
};
let Some(appdir) = appdir else {
return None;
};
if std::path::Path::new(gtk_im_module_file).starts_with(std::path::Path::new(appdir)) {
Some(system_cache_path)
} else {
None
}
}
#[cfg(target_os = "linux")]
fn apply_linux_webkit_rendering_workarounds() {
for (key, value) in linux_webkit_rendering_workarounds() {
@ -115,6 +155,18 @@ fn apply_linux_webkit_rendering_workarounds() {
) {
std::env::set_var("GDK_BACKEND", gdk_backend);
}
if let Some(gtk_im_module_file) = linux_appimage_system_gtk_immodules_cache(
std::env::var_os("APPIMAGE").as_deref(),
std::env::var_os("APPDIR").as_deref(),
std::env::var_os("GTK_IM_MODULE").as_deref(),
std::env::var_os("GTK_IM_MODULE_FILE").as_deref(),
linux_system_gtk3_immodules_cache_path(),
) {
// linuxdeploy-plugin-gtk points GTK_IM_MODULE_FILE at the bundled
// cache. That hides host IM modules such as fcitx5/ibus, so prefer the
// host GTK cache when the user has configured a GTK input method.
std::env::set_var("GTK_IM_MODULE_FILE", gtk_im_module_file);
}
}
fn show_main_window<R: tauri::Runtime>(app: &tauri::AppHandle<R>) {
@ -235,12 +287,14 @@ pub(crate) fn apply_desktop_settings(app: &tauri::AppHandle, desktop_settings: &
#[allow(clippy::items_after_test_module)]
mod tests {
use super::{
linux_appimage_wayland_backend_override, linux_webkit_rendering_workarounds,
native_window_decorations_override, should_hide_window_on_close, should_setup_desktop_tray,
should_show_main_window_after_setup,
linux_appimage_system_gtk_immodules_cache, linux_appimage_wayland_backend_override,
linux_webkit_rendering_workarounds, native_window_decorations_override, should_hide_window_on_close,
should_setup_desktop_tray, should_show_main_window_after_setup,
};
use std::ffi::OsStr;
const TEST_GTK3_IMMODULES_CACHE: &str = "/usr/lib/test/gtk-3.0/3.0.0/immodules.cache";
#[test]
fn hides_window_on_close_for_windows_and_macos() {
assert!(should_hide_window_on_close("windows"));
@ -302,6 +356,78 @@ mod tests {
assert_eq!(linux_appimage_wayland_backend_override(Some(OsStr::new("/tmp/DBX.AppImage")), None, None), None);
assert_eq!(linux_appimage_wayland_backend_override(None, Some(OsStr::new("wayland-0")), None), None);
}
#[test]
fn prefers_system_gtk_immodules_cache_for_appimage_input_methods() {
assert_eq!(
linux_appimage_system_gtk_immodules_cache(
Some(OsStr::new("/tmp/DBX.AppImage")),
Some(OsStr::new("/tmp/.mount_DBX123")),
Some(OsStr::new("fcitx5")),
Some(OsStr::new("/tmp/.mount_DBX123/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules.cache")),
Some(TEST_GTK3_IMMODULES_CACHE),
),
Some(TEST_GTK3_IMMODULES_CACHE)
);
assert_eq!(
linux_appimage_system_gtk_immodules_cache(
Some(OsStr::new("/tmp/DBX.AppImage")),
Some(OsStr::new("/tmp/.mount_DBX123")),
Some(OsStr::new("ibus")),
None,
Some(TEST_GTK3_IMMODULES_CACHE),
),
Some(TEST_GTK3_IMMODULES_CACHE)
);
}
#[test]
fn preserves_external_gtk_immodules_cache_overrides() {
assert_eq!(
linux_appimage_system_gtk_immodules_cache(
Some(OsStr::new("/tmp/DBX.AppImage")),
Some(OsStr::new("/tmp/.mount_DBX123")),
Some(OsStr::new("fcitx5")),
Some(OsStr::new("/opt/custom/immodules.cache")),
Some(TEST_GTK3_IMMODULES_CACHE),
),
None
);
}
#[test]
fn skips_system_gtk_immodules_cache_without_required_context() {
assert_eq!(
linux_appimage_system_gtk_immodules_cache(
None,
Some(OsStr::new("/tmp/.mount_DBX123")),
Some(OsStr::new("fcitx5")),
Some(OsStr::new("/tmp/.mount_DBX123/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules.cache")),
Some(TEST_GTK3_IMMODULES_CACHE),
),
None
);
assert_eq!(
linux_appimage_system_gtk_immodules_cache(
Some(OsStr::new("/tmp/DBX.AppImage")),
Some(OsStr::new("/tmp/.mount_DBX123")),
None,
Some(OsStr::new("/tmp/.mount_DBX123/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules.cache")),
Some(TEST_GTK3_IMMODULES_CACHE),
),
None
);
assert_eq!(
linux_appimage_system_gtk_immodules_cache(
Some(OsStr::new("/tmp/DBX.AppImage")),
Some(OsStr::new("/tmp/.mount_DBX123")),
Some(OsStr::new("fcitx5")),
Some(OsStr::new("/tmp/.mount_DBX123/usr/lib/x86_64-linux-gnu/gtk-3.0/3.0.0/immodules.cache")),
None,
),
None
);
}
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]