Desktop entries (桌面条目)
XDG 桌面条目规范 (XDG Desktop Entry specification) 为应用程序集成到实现了 XDG 桌面菜单 规范的 桌面环境 的应用菜单中定义了一套标准。
基础知识
桌面条目的格式类似于 INI 文件。它们必须具有 .desktop 扩展名,并包含一个 [Desktop Entry] 部分。在 [Desktop Entry] 部分中,名为 Type 和 Name 的键是必需的;其他键可以可选地定义其在应用程序菜单中的外观及其他行为。
三种可用的 Type (类型) 为:
Type=Application定义了如何启动应用程序以及它支持哪些 MIME 类型(由 XDG MIME 应用程序 使用)。配合 XDG 自启动,可以通过将应用程序条目放置在特定目录来使其自动启动。应用程序条目使用 .desktop 文件扩展名。参见 #应用程序的桌面条目。Type=Link定义了一个指向URL的快捷方式。链接条目使用 .desktop 文件扩展名。Type=Directory定义了应用程序菜单中子菜单的外观。目录条目使用 .directory 文件扩展名。
以下章节将粗略解释这些条目是如何创建和验证的。
桌面环境支持
下表描述了桌面环境对桌面条目规范各种功能的支持情况。
| 桌面环境 | 启动器 (软件包) | 自启动 | 应用程序 | 链接 |
|---|---|---|---|---|
| Cinnamon | gio (glib2) | 否 | 是 | 否 |
| GNOME | ||||
| GNOME Flashback | ||||
| MATE | ||||
| Deepin | dde-open1 (deepin-api) | 是 | 部分支持 | |
| Enlightenment | enlightenment_open (enlightenment) | |||
| KDE Plasma | kde-open2 (kde-cli-tools) | 是 | 是 | 是 |
| LXDE | pcmanfm (pcmanfm) | |||
| LXQt | pcmanfm-qt (pcmanfm-qt) | |||
| Xfce | exo-open3 (exo) | |||
| 环境无关 | gtk-launch4 (gtk3) | 否 | 部分支持 | 否 |
| dex (dex) | 是 | 是 | 否 | |
| xdg-open (xdg-utils) | 否 | 有 Bug | 否 | |
| app2unit5 (app2unitAUR) | 否6 | 是 | 是 | |
| uwsm app5 (uwsm) | 否6 | 是 | 否 |
- 类型为 Application 的 .desktop 文件必须设置可执行权限位才能由 dde-open 启动
- 如果未设置
KDE_SESSION_VERSION,则将使用来自 konqueror 的 kfmclient 代替。(不过,KDE Plasma 在任何情况下都应该设置此变量。) - 也会尝试使用 gio (来自 glib2)
- 仅当应用程序位于
/usr/share/applications中时 - 专为 systemd 管理的图形会话设计
- Systemd 原生管理 XDG 自启动
用法
用户通常通过其桌面环境的主菜单(如 GNOME 的“活动概览”)、停靠栏 (dock) 或类似 dmenu 的快捷键启动器与桌面条目进行交互。
主菜单条目通常由新程序安装在全系统位置,但用户可以在自己的主目录中创建。菜单条目可以使用下文提到的图形工具或普通的文本编辑器进行修改。
桌面条目也可以通过命令行调用,使用像 dex 这样的工具。
$ dex /usr/share/applications/firefox.desktop
应用程序的桌面条目
应用程序的桌面条目(即 .desktop 文件)主要由一个指向可执行文件的路径及一些元数据组成。它们必须具有 Type=Application 并且至少包含 Name= 和 Exec= 键,以便在磁盘上定位可执行文件。
对于全系统安装的应用程序,这些文件通常位于 /usr/share/applications/ 或 /usr/local/share/applications/;对于特定用户的应用程序,则位于 ~/.local/share/applications/。用户条目优先于系统条目,可用于(例如)隐藏或更改系统条目的默认图标。
.desktop 文件示例
以下是一个用于启动应用程序的 .desktop 文件示例,附带解释每个键的注释。它仅用于提供直观印象,并未展示如何利用所有可能的条目键。
全系统应用程序条目通常在 /usr/share/applications 中找到;你可以使用文本编辑器在 ~/.local/share/applications 中创建自己的条目,或者使用可用的工具来协助创建。
~/.local/share/applications/jmemorize.desktop
[Desktop Entry] # The type as listed above Type=Application # The version of the desktop entry specification to which this file conforms Version=1.0 # The name of the application Name=jMemorize # A comment which can/will be used as a tooltip Comment=Flash card based learning tool # The path to the folder in which the executable is run Path=/opt/jmemorise # The executable of the application, possibly with arguments. Exec=jmemorize # The name of the icon that will be used to display this entry Icon=jmemorize # Describes whether this application needs to be run in a terminal or not Terminal=false # Describes the categories in which this entry should be shown Categories=Education;Languages;Java;
应用程序条目中的常用键
所有公认的条目都可以在 freedesktop 网站上找到。以下是一些示例:
Type(必需)- 定义该桌面条目的类型,如上文所述(必需);通常为
Type=Application
- 定义该桌面条目的类型,如上文所述(必需);通常为
版本- 指定该条目符合的桌面条目规范版本(可选)
Name(必需)GenericName、Comment和Keywords- 该条目的菜单项名称或图标名称,以及其他描述性信息
TryExec和Exec- 当
Type=Application时,这些键指定了要运行的目标程序的位置
- 当
虽然用户界面(例如主菜单)并不总是显示 Comment 和 Keywords,但它们可以帮助用户根据关键字或概念定位应用程序。例如:
Name=Pidgin GenericName=Internet messenger
或者
Name=NoteCase GenericName=Note manager Comment=NoteCase is a hierarchical note manager (outliner), organizing notes in a tree-like structure
一些最佳实践:
Name应该是应用程序的官方名称,就像它出现在标题栏或“关于”框中那样GenericName是你通常对执行此类功能的应用程序的统称,例如,Firefox 是一个“Web 浏览器”
Exec 键
应用程序条目中的 Exec= 键通常是预期在用户的 搜索路径 (PATH) 中的可执行文件名,但为了更高的安全性,也可以指定绝对路径。
Exec 键接受几个“字段代码”,这些代码可用于向启动的程序传递参数,例如,当用作拖放目标或被识别为打开特定类型文件或 URL 的首选应用程序时。这些参数在传递给程序时会保留内部空格和 shell 元字符,因此你不需要(过多)担心加引号的问题。
以下是最有用的字段代码:
| 字段代码 (参考) | 展开为 |
|---|---|
%f, %F |
单个文件名,或文件列表,每个作为单独的参数 |
%u, %U |
单个 URL,或 URL 列表 |
%i
|
给程序的两个单独参数:--icon,后跟 Icon 键的值 |
Flatpak 文件转发
Flatpak 应用程序的 Exec 键通常包含一些 flatpak run 独有的语法。
Exec=/usr/bin/flatpak run --command=imhex --file-forwarding net.werwolv.ImHex @@u %U @@
详见 flatpak-run(1),简而言之:
--file-forwarding […] all arguments that are enclosed between a pair of '@@' arguments are interpreted as file paths, exported in the document store, and passed to the command in the form of the resulting document path. Arguments between '@@u' and '@@' are considered uris, and any file: uris are exported. The exports are non-persistent and with read and write permissions for the application.
上下文菜单操作
一些桌面环境和文件管理器还会通过桌面条目注册上下文操作,例如 选中文件后的右键菜单操作。Pantheon 就是一个例子,它使用名为 Contractor 的后台服务和扩展名为 .contract 的桌面条目。
这是一个简单的示例,使用 notify-send(1) 发送包含所选文件路径的桌面通知:
~/.local/share/contractor/notify-send.contract
[Contractor Entry] Name=Notify Icon=dialog-information Description=Create a notify-send notification with the current filename(s) # appear in the context menu for every file type except directories MimeType=!inode; TryExec=notify-send # %i is expanded as '--icon <Icon>'! Exec=notify-send %i -u low "Message from Files" "%F"
这是一个更复杂的示例,它将并行地将任何选中的 PNG 文件转换为 PNM:
~/.local/share/contractor/png-to-pnm.contract
[Contractor Entry]
Name=Convert to PNM
Icon=image-x-generic
Description=Convert PNGs to PPMs
MimeType=image/png;
TryExec=parallel
TryExec=pngtopnm
# from the spec:
# > Note that the general escape rule for values of type string states
# > that the backslash character can be escaped as ("\\") as well and that
# > this escape rule is applied before the quoting rule.
Exec=sh -c 'parallel pngtopnm {} \\> {.}.pnm ::: "$@"' parallel %F
上述内容中需要注意的一点是,如果任一 TryExec= 键执行失败,该条目将不会显示。阅读规范中关于引号的内容也可能有所启发,但通常它的行为与你在 shell 中习惯的一样,只是额外要求必须使用 %% 来表示字面意义上的 %。
在调试复杂的命令行时,可以在 Exec 命令前加上 echo 并检查系统日志中的输出(例如使用 journalctl -f SYSLOG_IDENTIFIER=org.elementary.Contractor),注意哪些字符是被字面传递的,哪些不是。
维护
应用程序的桌面条目通常由软件包的安装脚本自动就位,无需过多关注。然而,随着时间的推移,损坏或过时的 .desktop 文件确实会积累,特别是那些安装在你的主目录中的文件。
当桌面条目的 Exec= 或 TryExec= 所命名的可执行文件在文件系统中找不到时,该条目应该会自动从主菜单和其他启动器中隐藏。尽管如此,时不时对 ~/.local/share/applications 进行清理仍然是值得的。以下章节描述了如何实现这一点。
验证
由于某些键随着时间的推移已被弃用,你可能希望使用 desktop-file-validate(1) 来验证你的桌面条目,该工具是 desktop-file-utils 软件包的一部分。要进行验证,请运行:
$ desktop-file-validate your_file.desktop
这将为你提供非常详细且有用的警告和错误消息。
安装
使用 desktop-file-install(1) 将桌面文件安装到目标目录。例如:
$ desktop-file-install --dir=$HOME/.local/share/applications ~/app.desktop
这对于通过编辑选项自定义现有的桌面条目(例如来自 /usr/share/applications 的条目)也非常有用。
更新桌面条目数据库
通常,桌面环境会自动检测到桌面条目的更改。
如果情况并非如此,且你想要强制更新 ~/.local/share/applications 中定义的桌面条目,请运行以下命令:
$ update-desktop-database ~/.local/share/applications
-v (详细) 参数以显示可能的桌面条目错误。图标
另请参见 图标主题规范 (Icon Theme Specification)。
常用图像格式
以下是常用于图标的图像格式的简要概述。
| 扩展名 | 全名和/或描述 | 图形类型 | 容器格式 | 支持情况 |
|---|---|---|---|---|
| .png | 便携式网络图形 | 位图 | 否 | 是 |
| .svg(z) | 可缩放矢量图形 | 矢量 | 否 | 是(可选) |
| .xpm | X 像素图 | 位图 | 否 | 是(已弃用) |
| .gif | 图形交换格式 | 位图 | 否 | 否 |
| .ico | MS Windows 图标格式 | 位图 | 是 | 否 |
| .icns | Apple 图标图像 | 位图 | 是 | 否 |
转换图标
另见 ImageMagick#用法。
如果你偶然发现一个图标格式不被 freedesktop.org 标准支持(如 gif 或 ico),你可以使用 magick 工具(它是 imagemagick 软件包的一部分)将其转换为支持/推荐的格式,例如:
$ magick icon_name.gif icon_name.png
如果你从 ico 这样的容器格式进行转换,你将获得 ico 文件中封装的所有图像,形式为 icon_name-number.png。如果你想知道图像的大小,或者像 ico 这样的容器文件中的图像数量,可以使用 identify 工具(同样属于 imagemagick 软件包):
$ identify /usr/share/vlc/vlc48x48.ico
/usr/share/vlc/vlc48x48.ico[0] ICO 32x32 32x32+0+0 8-bit DirectClass 84.3kb /usr/share/vlc/vlc48x48.ico[1] ICO 16x16 16x16+0+0 8-bit DirectClass 84.3kb /usr/share/vlc/vlc48x48.ico[2] ICO 128x128 128x128+0+0 8-bit DirectClass 84.3kb /usr/share/vlc/vlc48x48.ico[3] ICO 48x48 48x48+0+0 8-bit DirectClass 84.3kb /usr/share/vlc/vlc48x48.ico[4] ICO 32x32 32x32+0+0 8-bit DirectClass 84.3kb /usr/share/vlc/vlc48x48.ico[5] ICO 16x16 16x16+0+0 8-bit DirectClass 84.3kb
如你所见,示例 .ico 文件虽然其名称可能暗示是一个 48x48 的单一图像,但实际上包含不少于 6 种不同的尺寸,其中一个甚至大于 48x48,即 128x128。
或者,你可以使用 icotool (来自 icoutils) 从 ICO 容器中提取 PNG 图像:
$ icotool -x icon_name.ico
要从 .icns 容器中提取图像,可以使用 icns2png (由 libicns 提供):
$ icns2png -x icon_name.icns
获取图标
虽然随附 .desktop 文件的软件包几乎肯定包含一个或一组图标,但有时开发人员没有创建 .desktop 文件,但可能仍然随附了图标。因此,一个好的开始是在源码包中查找图标。
例如,如果源码包中图像非常多,你可以先用 find 过滤扩展名,然后用 grep 进一步过滤某些关键字,如软件包名称、"icon"、"logo" 等。
$ find /path/to/source/package -regex ".*\.\(svg\|png\|xpm\|gif\|ico\)$"
如果应用程序的开发人员没有在其源码包中包含图标,下一步就是在其网站上搜索。
有些项目,如 tvbrowserAUR,有一个 美工/徽标页面,在那里可以找到额外的图标。如果一个项目是跨平台的,可能会出现这样一种情况:即使 Linux/UNIX 软件包没有附带图标,Windows 软件包也可能提供。如果项目使用 CVS/SVN 等版本控制系统,且你对其有一定经验,也可以考虑在其中浏览图标。
如果一切都失败了,该项目可能暂时还没有图标/徽标。
图标路径
freedesktop.org 标准指定了程序查找图标的顺序和目录:
$HOME/.icons(为了向后兼容)$XDG_DATA_DIRS/icons/usr/share/pixmaps
工具
Arronax
Arronax 是一个用于创建和修改应用程序及位置桌面条目的图形程序。安装 arronaxAUR 软件包即可使用。
Alacarte
alacarte 是一个用于 GNOME 的图形化菜单编辑器,使用 freedesktop.org 菜单规范。它还支持覆盖桌面条目。
jdDesktopEntryEdit
jddesktopentryeditAUR 是一个使用 Qt 编写的编辑桌面条目的图形程序。
MenuLibre
menulibreAUR 是一个使用 GTK 的图形化菜单编辑器,在简洁、易用的界面中提供现代功能。
LibreMenuEditor
libre-menu-editorAUR 是一个用于编辑桌面条目的图形程序,旨在功能丰富且对初学者友好。
它使用带有 libadwaita 的 GTK 并遵循 GNOME 的界面指南,但设计用于在任何符合 freedesktop.org 标准的桌面环境中工作。
gendesk
gendesk 起初是一个专门用于 Arch Linux 的工具,通过直接从 PKGBUILD 文件中获取所需信息来生成 .desktop 文件。现在它是一个接受命令行参数的通用工具。
如果可以获取,图标可以自动从 openiconlibrary 下载。(图标源是可配置的)。
如何使用
- 将
gendesk添加到 makedepends
- 以如下方式开始
prepare()函数:
gendesk --pkgname "$pkgname" --pkgdesc "$pkgdesc"
- 或者,如果已经提供了图标(例如 $pkgname.png)。
-n标志用于不下载图标或使用默认图标。示例:
gendesk -n --pkgname "$pkgname" --pkgdesc "$pkgdesc"
$srcdir/$pkgname.desktop将被创建,并可以在package()函数中通过以下方式安装:
install -Dm644 "$pkgname.desktop" "$pkgdir/usr/share/applications/$pkgname.desktop"
- 图标可以通过以下方式安装:
install -Dm644 "$pkgname.png" "$pkgdir/usr/share/pixmaps/$pkgname.png"
- 使用
--name='程序名称'为菜单条目选择名称。
- 使用
--exec='/opt/some_app/elf --some-arg --other-arg'设置 exec 字段。
- 更多信息请参见 gendesk 项目。
lsdesktopf
lsdesktopfAUR 可以列出可用的 .desktop 文件或搜索其内容。
$ lsdesktopf $ lsdesktopf --list $ lsdesktopf --list gtk zh_TW,zh_CN,en_GB
它还可以执行与 MIME 类型相关的搜索。参见 XDG MIME 应用程序#lsdesktopf。
fbrokendesktop
fbrokendesktopAUR Bash 脚本可以检测指向不存在路径的损坏 Exec 值。不带任何参数时,它使用 DskPath 数组中的预设目录。它仅显示带有完整路径和缺失文件名的损坏 .desktop 文件。
示例
$ fbrokendesktop $ fbrokendesktop /usr $ fbrokendesktop /usr/share/xsessions/icewm.desktop
技巧与提示
修改桌面文件
对于全系统 .desktop 文件(例如从软件包安装的文件),首先将相关的 .desktop 文件(例如从 /usr/share/applications/)复制到 $XDG_DATA_HOME/applications/(例如 ~/.local/share/applications/)。这可以防止你的更改在系统升级过程中因软件包更新而被覆盖。本地特定用户的 .desktop 文件应自动优先于全系统文件。现在你可以根据需要修改本地特定用户的 .desktop 文件。
$XDG_CONFIG_HOME/autostart 中可能已经有一份系统桌面条目的副本。如果你只想修改自启动时的行为,请编辑此文件。否则,如果你想修改所有情况下的行为,你应该:- 将桌面文件从
$XDG_CONFIG_HOME/autostart/移动到$XDG_DATA_HOME/applications。 - 使用
ls -l确保此桌面条目是一个你可以编辑的常规文件,而不是指向系统位置的链接。如果是链接,请按上述方法将其替换为原始文件的副本。 - 创建到用户应用程序目录的符号链接(为方便起见,此处替换了默认 XDG 目录):
ln -s ~/.local/share/applications/desktop_entry ~/.config/autostart/
现在,应用程序启动器中的文件将与自启动的文件保持一致。
修改环境变量
要设置环境变量,请在 .desktop 文件中编辑 Exec= 行,首先使用 env(1) 命令设置变量。例如,将原始行注释掉:
~/.local/share/applications/abiword.desktop
... # Exec=abiword %U Exec=env LANG=he_IL.UTF-8 abiword %U ...
如果存在 DBusActivatable=true,也请将其删除(或设置为 false),因为它会导致 Exec 行被忽略。[1]
此技术可用于设置特定应用程序的桌面主题,前提是你始终从系统菜单或利用桌面条目规范的其他启动器启动该应用程序:
~/.local/share/applications/gvim-dark.desktop
... Exec=/usr/bin/env GTK_THEME=Adwaita:dark gvim -f %F ...
有关更多详细信息,请参见 暗黑模式切换。
修改命令行参数
要更改或添加命令行参数,请编辑 Exec= 行以追加所需的选项。例如,将原始行注释掉:
~/.local/share/applications/steam.desktop
... # Exec=/usr/bin/steam-runtime %U Exec=/usr/bin/steam-runtime -no-browser %U ...
如果存在 DBusActivatable=true,也请将其删除(或设置为 false),因为它会导致 Exec 行被忽略。[2]
隐藏桌面条目
桌面条目的可见性可以通过多种方式控制。更多信息请参见 桌面条目规范。在你的 .desktop 文件中添加以下行之一:
- 对于所有桌面环境,选择以下一项(或两项):
- 对于不希望在菜单中显示的应用程序,添加
NoDisplay=true行。 - 对于你认为已删除且不希望在菜单中显示的应用程序,添加
Hidden=true行。
- 对于不希望在菜单中显示的应用程序,添加
- 对于指定的桌面环境,选择以下一项,其中
desktop_names是以分号分隔的桌面环境列表(例如GNOME,GNOME;Xfce;KDE;):- 添加
NotShowIn=desktop_names行以仅在指定的桌面环境中隐藏条目。 - 添加
OnlyShowIn=desktop_names行以仅在指定的桌面环境中显示条目。
- 添加