[Application sharing] GTK应用打包成玲珑格式时遇到的输入法问题修复参考
Tofloor
poster avatar
Ziggy
deepin
2024-07-05 10:21
Author

出处

Origin author: myml
Modified by: ziggy
https://github.com/linglongdev/org.deepin.browser/blob/main/gtk-fcitx-fix-note.md

GTK 应用打包成玲珑后,使用拼音输入法输入选词较快时,选词后漏词或变成字母展示。本案例以浏览器(org.deepin.browser)开展流程说明。
注: 本案例使用了部分vs code的第三方插件功能,请注意是否符合操作要求

Issues: https://github.com/linuxdeepin/developer-center/issues/9409

问题排查

玲珑环境中的gtk based应用没有使用fcitx5的gtk插件导致玲珑gtk应用在使用fcitx5输入框架时存在异常

问题验证思路

需要确定下问题是否因为缺少插件导致,以下步骤也可用于排查其他应用缺少插件、依赖库等问题。

  1. 首先使用 ll-cli 安装 BUG 中反馈的浏览器(org.deepin.browser)应用,
  2. 切换到 /var/lib/linglong/layers/main/org.deepin.browser/6.5.3.2/x86_64/runtime 目录,这是浏览器的安装目录,查看目录中的 info.json 文件,可以看到浏览器使用的 base 和 runtime 版本
  3. 切换到 /var/lib/linglong/layers/main/org.deepin.foundation/20.0.0.26/x86_64/runtime/ 目录,这是浏览器使用的 base 目录,将 files 目录改名字为 files.bk,再复制 files.bk 为 files(用于之后恢复原始的 base 目录)。
  4. 使用 sudo chroot files进入 base,执行 apt update && apt install fcitx5-frontend-gtk2 (浏览器使用的是 gtk2,如果是 gtk3 的应用则安装 fcitx5-frontend-gtk3)
  5. 安装后再使用 ll-cli run org.deepin.browser 启动浏览器,验证问题得到解决,确实是 base 和 runtime 中缺少 gtk fcitx 插件导致的问题。

退出 chroot 环境,删除 files 目录,更改 files.bk 为 files

修复方案

问题得到验证后,需要考虑修复方案,最简单的当然时在 base 或 runtime 中添加相应的依赖库。

但考虑到 base 和 runtime 需要限制体积并保持兼容性,所有先从应用层修复问题。

玲珑支持在应用构建时安装 deb 包,可以在 org.deepin.browser 的 linglong.yaml 文件中通过设置sources字段添加 fcitx5-frontend-gtk2 deb 包依赖。

sources:
  # linglong:gen_deb_source sources amd64 https://pools.uniontech.com/deepin-beige beige main community
  # linglong:gen_deb_source install fcitx5-frontend-gtk2

注:
上述字符中的"#"存在实际作用,请勿当成注释符号删除。
有关 vscode linglong 插件的具体用法请参照vscode插件详情页中的说明

在vs code中安装来自myml的插件"linglong"后引用 vscode linglong 插件的 Gen deb source功能,自动生成相关的下载链接。

然后使用 ll-builder build 构建,使用 ll-builder run 进行测试,发现插件并未生效,漏字情况仍然存在。

搜索到 fcitx5-frontend-gtk2 包中有一个名字叫 fcitx5-gtk2-immodule-probing 的二进制,可用来探测环境

➜  ~ fcitx5-gtk2-immodule-probing
GTK_IM_MODULE=im

在宿主机使用 strace 跟踪二进制的系统调用,可查看到 fcitx5-gtk2-immodule-probing 尝试读取的文件中,

➜  ~ strace fcitx5-gtk2-immodule-probing 2>&1|grep openat
...
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gtk-2.0/2.10.0/immodules.cache", O_RDONLY) = 5
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gtk-2.0/2.10.0/immodules/im-fcitx5.so", O_RDONLY|O_CLOEXEC) = 5
...

根据经验判断 immodules.cache 这个文件很可疑,使用 cat 查看文件内容,在开头写着文件由 gtk-query-immodules-2.0 生成,搜索该命令相关文档了解到,可以使用 --update-cache 参数更新 immodules.cache,在更新时可指定 so 文件路径。

由于玲珑的 base 在应用构建和运行时是只读的,无法直接更新 /usr 下的 immodules.cache 文件,使用 dpkg -S gtk-query-immodules-2.0查到该命令是 libgtk2.0-0 包里面的,再使用 apt source libgtk2.0-0下载源码,找到更新 immodules.cache 文件的部分

  if (argc > 1 && strcmp (argv[1], "--update-cache") == 0)
    {
      cache_file = gtk_rc_get_im_module_file ();
      first_file = 2;
    }

  contents = g_string_new ("");
  g_string_append_printf (contents,
                          "# GTK+ Input Method Modules file\n"
                          "# Automatically generated file, do not edit\n"
                          "# Created by %s from gtk+-%d.%d.%d\n"
                          "#\n",
                          argv[0],
                          GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
...

gchar *
gtk_rc_get_im_module_file (void)
{
  const gchar *var = g_getenv ("GTK_IM_MODULE_FILE");
  gchar *result = NULL;

  if (var)
    result = g_strdup (var);

  if (!result)
    {
      if (im_module_file)
	result = g_strdup (im_module_file);
      else
        result = gtk_rc_make_default_dir ("immodules.cache");
    }

  return result;
}

可以看到 cache_file 是使用 gtk_rc_get_im_module_file 获取的,再继续跟踪 gtk_rc_get_im_module_file函数,会优先使用 GTK_IM_MODULE_FILE环境变量,没有环境变量才使用默认目录。

修复实施

在 linglong.yaml 的 build 添加以下内容

# 环境变量 GTK_IM_MODULE_FILE 到应用目录
export GTK_IM_MODULE_FILE=$PREFIX/lib/x86_64-linux-gnu/gtk-2.0/2.10.0/immodules.cache
# 更新缓存文件
/usr/lib/x86_64-linux-gnu/libgtk2.0-0/gtk-query-immodules-2.0 --update-cache $PREFIX/lib/x86_64-linux-gnu/gtk-2.0/2.10.0/immodules/im-fcitx5.so

这样就可以在构建应用时生成带 fctix 插件的 immodules.cache,但运行应用时仍会到默认的 /usr 目录查找,所以需要在运行应用之前再设置 GTK_IM_MODULE_FILE 环境变量。

由于 org.deepin.browser 的入口文件是一个 bash 脚本,在构建时使用 sed 添加环境变量设置即可。(如果应用入口文件是二进制,则需要自己生成一个脚本用作入口文件)

在 linglong.yaml 的 build 添加以下内容

sed -i "2i\export GTK_IM_MODULE_FILE=$PREFIX/lib/x86_64-linux-gnu/gtk-2.0/2.10.0/immodules.cache" $PREFIX/bin/browser

修改完成后,依次执行build、install、run操作来验证是否完成修复

Reply Favorite View the author
All Replies
DebuggerX
deepin
2024-07-05 11:11
#1

这个问题终于要解决了,撒花~输入问题确实太影响体验,太劝退了。

不过看下来还需要打包者自行处理一些事情?按我理解其实打包工具在打包过程中应该是有办法判断出是否需要“修复”的,不能自动处理吗?

Reply View the author
阿尼樱奈奈
Moderator
2024-07-05 12:17
#2
Reply View the author
Ziggy
deepin
2024-07-05 14:38
#3
DebuggerX

这个问题终于要解决了,撒花~输入问题确实太影响体验,太劝退了。

不过看下来还需要打包者自行处理一些事情?按我理解其实打包工具在打包过程中应该是有办法判断出是否需要“修复”的,不能自动处理吗?

这个属于救急方案,论从根源上解决问题这个后面会评估看看有没有更好的处理方法

Reply View the author
myml
Super Moderator
Developer
2024-07-08 14:22
#4

目前会先将热门的几个应用单独修复,后面会在base和runtime中解决

Reply View the author