Rofi 缩略图系统(rofi-thumbnails)完整指南:XDG Thumbnailer、-preview-cmd 自定义命令与 AppArmor 排障
【免费下载链接】rofiRofi: A window switcher, application launcher and dmenu replacement项目地址: https://gitcode.com/gh_mirrors/ro/rofi
rofi(窗口切换器、应用启动器与 dmenu 替代品)从 1.7 系列开始支持为所有存在 XDG 兼容 thumbnailer 的文件类型显示缩略图。本文基于仓库中的 mkdocs/docs/1.7.6/rofi-thumbnails.5.markdown 手册页,深入讲解thumbnail://前缀协议、.thumbnailer文件格式与缓存目录机制、-preview-cmd自定义缩略图生成命令,以及 Ubuntu/Debian 等发行版上的 AppArmor 问题与解决方案。读完本文,你将能够在 filebrowser/recursivebrowser 模式、dmenu 模式及自定义脚本中完整配置并调优 rofi 的缩略图显示能力。
概述:rofi 如何显示文件缩略图
手册页开篇即说明核心能力:rofi 现在可以为系统中存在 XDG 兼容 thumbnailer 的所有文件类型显示缩略图(**rofi** is now able to show thumbnails for all file types where an XDG compatible thumbnailer is present in the system)。
在 filebrowser(文件浏览器)和 recursivebrowser(递归文件浏览器)模式下,只要以-show-icons参数启动 rofi,缩略图显示就会默认启用。从源码实现看,这一行为由 source/modes/filebrowser.c 的_get_icon()函数体现:
- 若文件本身是图片(通过
rofi_icon_fetcher_file_is_image()判断),直接按路径查询图标; - 若文件是普通文件,则构造
thumbnail://前缀的查询名(g_strconcat("thumbnail://", dr->path, NULL))交给图标抓取器; - 目录等类型则使用类型图标名。
而在自定义用户脚本或 dmenu 模式中,你可以通过给\0icon\x1f后指定的文件名加上thumbnail://前缀,利用 XDG thumbnailer 生成条目图标。下面是手册页给出的完整可运行示例:
echo -en "EntryName\0icon\x1fthumbnail://path/to/file\n" | rofi -dmenu -show-icons-show-icons选项在 doc/rofi.1.markdown 中定义为「加载并在默认主题中显示图标」,默认值为关闭(见 config/config.c 中的.show_icons = FALSE),在 source/xrmoptions.c 中注册为命令行/XResources 可配置项。同时还可搭配-icon-theme指定图标主题(默认使用桌面环境主题,Adwaita与gnome作为回退主题,见 source/rofi-icon-fetcher.c)。
XDG Thumbnailer 详解
.thumbnailer 文件格式与存放位置
XDG thumbnailer 是后缀为.thumbnailer的文件,结构类似用于启动应用的.desktop文件。它们存放在:
/usr/share/thumbnailers/(系统级)$HOME/.local/share/thumbnailers/(用户级)
文件中包含一组 mimetype 列表(针对这些类型可以生成缩略图),以及一条生成图片的命令字符串。手册页给出的librsvg.thumbnailer(使用 librsvg 处理 svg 文件的 thumbnailer)完整示例:
[Thumbnailer Entry] TryExec=/usr/bin/gdk-pixbuf-thumbnailer Exec=/usr/bin/gdk-pixbuf-thumbnailer -s %s %u %o MimeType=image/svg+xml;image/svg+xml-compressed;其中关键字段:
| 字段 | 含义 |
|---|---|
[Thumbnailer Entry] | 组名,源码中以THUMBNAILER_ENTRY_GROUP宏定义(source/rofi-icon-fetcher.c) |
TryExec | 探测性可执行文件,用于判断 thumbnailer 是否可用 |
Exec | 实际生成缩略图的命令模板 |
MimeType | 以分号分隔的 MIME 类型列表,该 thumbnailer 可处理这些类型 |
Exec中的占位符会被 rofi 在运行时替换(见 source/rofi-icon-fetcher.c 的setup_thumbnailer_command()):
| 占位符 | 替换内容 |
|---|---|
%i | 输入文件名 |
%u | 输入文件的 URI 编码形式 |
%o | 缩略图输出路径 |
%s | 请求的缩略图尺寸 |
缩略图缓存目录与命名规则
生成的图片以输入文件的 md5 哈希值命名,并根据尺寸放入 XDG 缩略图目录:
$HOME/.cache/thumbnails/normal/ (≤128px) $HOME/.cache/thumbnails/large/ (≤256px) $HOME/.cache/thumbnails/x-large/ (≤512px) $HOME/.cache/thumbnails/xx-large/ (>512px)这一逻辑在 source/rofi-icon-fetcher.c 的rofi_icon_fetcher_get_thumbnail()中实现:对条目名计算 MD5,按requested_size选择目录(128/256/512/1024 四档),文件名为<md5>.png,并自动创建目录(g_mkdir_with_parents(thumb_dir, 0700))。
这些缩略图既被 rofi 作为条目图标加载,也可被 Thunar、Caja、KDE Dolphin 等文件管理器复用。反向同样成立:如果缩略图目录中已存在某个文件对应的缩略图(无论由 rofi 还是文件管理器生成),rofi 会直接加载已有缩略图而不重新调用 thumbnailer(手册页明确说明,源码中体现为 source/rofi-icon-fetcher.c 的g_file_test(icon_path, G_FILE_TEST_EXISTS)检查)。
如果某个文件找不到合适的 thumbnailer,rofi 会回退到图标主题中对应的 mimetype 图标——源码中表现为将 mimetype 中的/替换为-后作为图标名查询(如text/plain→text-plain,见 source/rofi-icon-fetcher.c)。
加载与执行流程(源码视角)
thumbnailer 的加载与调用链路清晰地位于 source/rofi-icon-fetcher.c:
- 初始化加载:
rofi_icon_fetcher_init()(L273-L319)通过rofi_icon_fetcher_load_thumbnailers()遍历用户数据目录(g_get_user_data_dir())与系统数据目录(g_get_system_data_dirs()),找到所有.thumbnailer后缀文件,解析Exec与MimeType,建立mimetype → 命令的哈希表(L105-L159)。 - 图标请求:界面线程通过
rofi_icon_fetcher_query_advanced()(L752 起)发起查询,将任务推入线程池(g_thread_pool_push),避免阻塞 UI。 - 工作线程处理:
rofi_icon_fetcher_worker()(L528-L750)检测到thumbnail://前缀后(L539),截取前缀之后的真实路径(&sentry->entry->name[12],thumbnail://恰好 12 个字符),按请求尺寸查找或生成缩略图。 - 命令执行:
rofi_icon_fetcher_create_thumbnail()(L223-L247)从哈希表取出命令,展开占位符后由exec_thumbnailer_command()(L204-L221)以g_spawn_sync同步执行;值得注意的是,命令前会附加nice -n 19,将缩略图生成进程的优先级降到最低(L173-L178),避免影响系统交互性能。 - 图标渲染:生成的 PNG 经
gdk_pixbuf_new_from_file_at_scale()按请求尺寸加载为 pixbuf,再转换为 cairo surface 供界面绘制(L702-L750)。
使用 -preview-cmd 自定义缩略图生成命令
对于通用条目名(例如一个脚本需要根据 URL 下载图标、或根据输入选择不同图标),可以放弃 XDG thumbnailer,改用自定义命令。手册页给出的语法:
rofi ... -preview-cmd 'path/to/script_or_cmd "{input}" "{output}" "{size}"'rofi 调用该脚本/命令时依次替换三个占位符:
| 占位符 | 替换内容 |
|---|---|
{input} | 输入条目图标名(即\0icon\x1fthumbnail://之后的部分) |
{output} | 缩略图输出文件名 |
{size} | 请求的缩略图尺寸 |
脚本/命令负责生成缩略图(尽可能尊重请求的尺寸)并保存到{output}指定的文件。也就是说,-preview-cmd完全接管了「如何把输入变成一个图片文件」这一步,输出结果仍会进入上述 XDG 缩略图缓存体系。
源码支撑位于 source/rofi-icon-fetcher.c:当条目名带thumbnail://前缀且config.preview_cmd != NULL时,工作线程计算目标缩略图路径;若文件不存在,则通过helper_parse_setup()将{input}、{output}、{size}替换为真实值,构造命令参数并调用exec_thumbnailer_command()执行。配置项默认值为 NULL(见 config/config.c),通过 source/xrmoptions.c 注册命令行选项,对应结构体字段在 include/settings.h。
一个典型的自定义脚本(示意)可以是:
#!/bin/bash # thumbnail-cmd.sh —— 被 rofi -preview-cmd 调用的自定义缩略图生成器 input="$1" # {input}: 图标名 / 条目名 output="$2" # {output}: 输出缩略图路径 size="$3" # {size}: 请求尺寸 # 例:从 URL 下载图片并缩放后写入 $output curl -fsSL "$input" | convert - -resize "${size}x${size}" "$output"使用时:rofi -dmenu -show-icons -preview-cmd '/path/to/thumbnail-cmd.sh "{input}" "{output}" "{size}"'。
处理 AppArmor 限制
在启用了 AppArmor 的发行版(如 Ubuntu、Debian)上,默认规则可能导致缩略图生成失败。手册页提供了两种解决路径。
方案一:直接停用 AppArmor
sudo systemctl stop apparmor sudo systemctl disable apparmor该方案简单但会全局关闭 AppArmor 保护,仅适合不依赖该安全模块的环境。
方案二:为 rofi 编写专属 AppArmor 策略(推荐)
将以下配置文件保存为/etc/apparmor.d/usr.bin.rofi(手册页原文),为 rofi 授予读写主目录、访问缩略图缓存及 NFS 所需的网络能力:
#vim:syntax=apparmor # AppArmor policy for rofi #include <tunables/global> /usr/bin/rofi { #include <abstractions/base> # TCP/UDP network access for NFS network inet stream, network inet6 stream, network inet dgram, network inet6 dgram, /usr/bin/rofi mr, @{HOME}/ r, @{HOME}/** rw, owner @{HOME}/.cache/thumbnails/** rw, }随后重载规则:
apparmor_parser -r /etc/apparmor.d/usr.bin.rofi要点说明:
- 该策略假设 rofi 二进制位于
/usr/bin/rofi,标准包安装即为此路径;若为自定义编译安装,需相应调整路径段; @{HOME}/.cache/thumbnails/** rw权限与上文缩略图缓存目录($HOME/.cache/thumbnails/{normal,large,x-large,xx-large})相对应,确保 rofi 能读取已有缓存并写入新生成的缩略图;- 网络访问规则服务于通过 NFS 共享的文件系统场景。
配置速查与注意事项
将本文涉及的核心配置汇总如下(均可在命令行或 XResources 中设置,注册位置见 source/xrmoptions.c):
| 配置项 | 作用 | 默认值 |
|---|---|---|
-show-icons | 加载并在默认主题中显示图标 | false |
-icon-theme | 指定图标主题,缺省用 DE 主题,回退 Adwaita/gnome | 系统默认 |
-preview-cmd | 自定义缩略图生成命令,占位符{input}/{output}/{size} | 未设置 |
实战注意点:
- filebrowser/recursivebrowser 模式:图片文件直接以原图路径查询,普通文件走
thumbnail://协议,目录用类型图标——这三类分支的处理见 source/modes/filebrowser.c; - 缓存复用:只要
$HOME/.cache/thumbnails/下已存在对应 md5 的缩略图,rofi 便不会重新调用 thumbnailer,因此文件管理器与 rofi 之间可以共享缓存、互相加速; - 低优先级执行:thumbnailer 进程会以
nice -n 19运行,大量文件首次浏览时缩略图会分批异步生成,界面不会卡顿; - 回退机制:没有合适 thumbnailer 时自动使用 mimetype 图标,保证列表仍然可读;
- AppArmor:遇到缩略图不生成、日志中出现权限拒绝类错误时,优先检查是否命中默认 AppArmor 限制,并采用上述专属策略而非全局禁用。
通过thumbnail://协议、XDG thumbnailer 标准、-preview-cmd扩展与缓存复用机制,rofi 的图标体系既能开箱即用地服务于文件浏览,又能被 dmenu 脚本和自定义启动器深度定制,形成一套完整、可预测的缩略图工作流。
【免费下载链接】rofiRofi: A window switcher, application launcher and dmenu replacement项目地址: https://gitcode.com/gh_mirrors/ro/rofi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考