Desktop Menu Specification #
Authors: Waldo Bastian <waldo.bastian@intel.com>
Francois Gouget <fgouget@codeweavers.com>
Alex Graveley <alex@ximian.com>
George Lebl <jirka@5z.com>
Havoc Pennington <hp@pobox.com>
Heinrich Wendel <h_wendel@cojobo.net>
Publication Date: 20 August 2016, Version: Version 1.1
This document defines how to construct a user-visible hierarchy of
applications, typically displayed as a menu. It allows third-party
software to add menu items that work for all desktops, and allows system
administrators to edit menus in a way that affects all desktops.
The basic scheme is very simple. Information about each application (menu
item) is stored in a desktop entry (see Desktop
Entry Standard (http://www.freedesktop.org/Standards/desktop-entry-spec)). Then an XML configuration file defines the
hierarchical arrangement (layout) of menu items, and which menu items are
actually displayed.
Things are complicated somewhat by the need to support legacy desktop
entry hierarchies, and the need to allow third parties to extend the menu
layout. Both of these issues are addressed by the idea of
merging two menu layouts.
In addition to a strict definition of the contents of each menu this
specification also foresees in a number of layout / presentation hints.
This part of the specification is optional, implementations may chose to
ignore these hints.
Files involved in this specification are located according to the "desktop
base directory specification" (http://www.freedesktop.org/Standards/basedir-spec).
Here are the files defined by this specification:
$XDG_CONFIG_DIRS
/menus/${XDG_MENU_PREFIX}
applications.menu
This file contains the XML definition of the main application
menu layout. The first file found in the search path should be
used; other files are ignored. This implies that if the user
has their own ${XDG_MENU_PREFIX}
applications.menu,
it replaces the system wide one.
(Though the user's menu may explicitly merge the system wide
one.)
Systems that offer multiple desktop environments and that want
to use distinct menu layouts in the different environments can
use differently prefixed .menu files. In this case the
$XDG_MENU_PREFIX
environment variable must
be set by the system to reflect the .menu file that is being
used.
For example if a system contains both the GNOME and the KDE
desktop environments it can decide to use
gnome-applications.menu as the menu layout in GNOME sessions
and kde-applications.menu as the menu layout in KDE sessions.
To correctly reflect this, it should set the
$XDG_MENU_PREFIX
environment variable to
"gnome-" respectively "kde-".
Implementations may chose to use .menu files with other names
for tasks or menus other than the main application menu. Such
usage is not covered by this specification.
$XDG_CONFIG_DIRS
/menus/applications-merged/
The default merge directories included in the
<DefaultMergeDirs> element. By convention, third parties
may add new <Menu> files in this location to create their
own sub-menus.
Note that a system that uses either gnome-applications.menu or
kde-applications.menu depending on the desktop environment in
use must still use applications-merged as the default merge
directory in both cases.
Implementations may chose to use .menu files with names other
than application.menu for tasks or menus other than the main
application menu. In that case the first part of the name of
the default merge directory is derived from the name of the
.menu file.
For example in a system that uses a preferences.menu file to
describe an additional menu, the default merge directories
included in the <DefaultMergeDirs> element in the
preferences.menu file would become
$XDG_CONFIG_DIRS
/menus/preferences-merged/
$XDG_DATA_DIRS
/applications/
This directory contains a .desktop file for each possible menu
item. Each directory in the $XDG_DATA_DIRS
search path should be used (i.e. desktop entries are collected
from all of them, not just the first one that exists). When two
desktop entries have the same name, the one appearing earlier in
the path is used.
The <DefaultAppDirs> element in a menu file indicates that
this default list of desktop entry locations should be scanned at
that point. If a menu file does not contain
<DefaultAppDirs>, then these locations are not scanned.
$XDG_DATA_DIRS
/desktop-directories/
This directory contains directory entries which may be associated
with folders in the menu layout. Each directory
in the search path should be used. Only files ending in
.directory are used; other files are ignored.
The <DefaultDirectoryDirs> element in a menu file indicates that
this default list of directory entry locations should be scanned at
that point. If a menu file does not contain
<DefaultDirectoryDirs>, then these locations are not scanned.
3 Extensions to the desktop entry format #
This specification adds three new fields to desktop
entries (http://www.freedesktop.org/Standards/desktop-entry-spec): Categories
,
OnlyShowIn
and NotShowIn
.
The Categories
field is a list of strings used to
classify menu items. For example, applications in the
AudioVideo
category might end up in the
"Sound & Video" submenu. Appendix A, Registered Categories
enumerates the standard categories. Categories not in this document
must be prefixed by the string "X-" indicating that they are extensions.
Categories are case-sensitive.
Desktop entries should list all categories that clearly apply. They should
not list categories that only vaguely or possibly apply, because the user
will end up seeing the same desktop entry in a half-dozen places. But
it's typical that several categories will apply to a given desktop entry.
The OnlyShowIn
field is a list of strings identifying
the environments that should display a given menu item. If an
OnlyShowIn
field is present, a given environment should
only display the menu item if the string identifying that environment is
present. The strings are case-sensitive. Appendix B, Registered OnlyShowIn Environments enumerates the strings to use for
some common environments.
The NotShowIn
field is a list of strings identifying
the environments that should not display a given menu item. If an
NotShowIn
field is present, a given environment should
only display the menu item if the string identifying that environment is
not present. The strings are case-sensitive. Appendix B, Registered OnlyShowIn Environments enumerates the strings to use for
some common environments.
Environments not in this document must be prefixed by the string "X-"
indicating that they are extensions. Environments are case-sensitive.
3.1 Examples of using Categories
and OnlyShowIn
#
A desktop entry for a Qt-based image viewer might contain
this Categories
line:
A desktop entry for Octave, a command-line mathematics program (which
would also have the field Terminal=true
), might have:
A desktop entry for a GNOME-specific calculator program
that should only appear in GNOME might have:
Note that the OnlyShowIn
field is a
list and thus ends in a semicolon.
Sometimes two menu layouts need to be merged. This is done when folding in
legacy menu hierarchies (see Section 7, “Legacy Menu Hierarchies”) and also
for files specified in <MergeFile> elements. A common case is that
per-user menu files might merge the system menu file. Merging is also used
to avoid cut-and-paste, for example to include a common submenu in
multiple menu files.
Merging involves a base <Menu> and a merged <Menu>. The base
is the "target" menu and the merged <Menu> is being added to it. The
result of the merge is termed the "combined menu."
As a preparatory step, the goal is to resolve all files into
XML elements. To do so, traverse the entire menu tree. For each
<MergeFile>, <MergeDir>, or <LegacyDir> element, replace
the <MergeFile>, <MergeDir>, or <LegacyDir> element with
the child elements of the root <Menu> of the file(s) being
merged. As a special exception, remove the <Name> element from the
root element of each file being merged. To generate a
<Menu> based on a <LegacyDir>, see
Section 7, “Legacy Menu Hierarchies”.
Continue processing until no <MergeFile>, <MergeDir>, or
<LegacyDir> elements remain, taking care to avoid infinite loops
caused by files that reference one another.
Once all files have been loaded into a single tree, scan the tree
recursively performing these steps to remove duplicates:
Consolidate child menus. Each group of child <Menu>s with the same
name must be consolidated into a single child menu with that name.
Concatenate the child elements of all menus with the same name, in
the order that they appear, and insert those elements as the
children of the last menu with that name.
Delete all the newly empty <Menu> elements, keeping the
last one.
Expand <DefaultAppDirs> and <DefaultDirectoryDirs>
elements to <AppDir> and <DirectoryDir> elements.
Consolidate duplicate <AppDir>, <DirectoryDir>,
and <Directory> elements by keeping the last one.
For <Directory> elements that refer to distinct directory
entries, all of them should be kept - if the last one points
to a nonexistent file, the one before that can be used instead,
and so forth.
Recurse into each child <Menu>, performing this list of
steps for each child in order.
After recursing once to remove duplicates, recurse a second time to
resolve <Move> elements for each menu starting with any child
menu before handling the more top level menus.
So the deepest menus have their <Move> operations performed first.
Within each <Menu>, execute <Move> operations in the order
that they appear. If the destination path does not exist, simply relocate
the origin <Menu> element, and change its <Name> field to
match the destination path. If the origin path does not exist, do
nothing. If both paths exist, take the origin <Menu> element,
delete its <Name> element, and prepend its remaining child elements
to the destination <Menu> element.
If any <Move> operations affect a menu, then re-run the
steps to resolve duplicates in case any duplicates have been
created.
Finally, for each <Menu> containing a <Deleted> element which
is not followed by a <NotDeleted> element, remove that menu and all
its child menus.
Merged menu elements are kept in order because <Include> and
<Exclude> elements later in the file override <Include> and
<Exclude> elements earlier in the file. This means that if the user's
menu file merges the system menu file, the user can always override what
the system menu specifies by placing elements after the <MergeFile>
that incorporates the system file.
To prevent that a desktop entry from one party inadvertently cancels out
the desktop entry from another party because both happen to get the same
desktop-file id it is recommended that providers of desktop-files ensure that
all desktop-file ids start with a vendor prefix. A vendor prefix
consists of [a-zA-Z] and is terminated with a dash ("-"). Open Source
projects and commercial parties are encouraged to use a word or phrase,
preferably their name, as prefix for which they hold a trademark. Open Source
applications can also ask to make use of the vendor prefix of another open
source project (such as GNOME or KDE) they consider themselves affiliated
with, at the discretion of these projects.
For example, to ensure that GNOME applications start with a vendor prefix of "gnome-",
it could either add "gnome-" to all the desktop files it installs in
datadir/applications/
or it could
install desktop files in a datadir/applications/gnome
subdirectory. When including legacy menu hierarchies the prefix
argument
of the <LegacyDir> element can be used to specify a prefix.
After merging the menus, the result should be a single menu layout
description. For each <Menu>, we have a list of directories where
desktop entries can be found, a list of directories where directory
entries can be found, and a series of <Include> and <Exclude>
directives.
For each <Menu> element, build a pool of desktop entries by
collecting entries found in each <AppDir> for the menu element. If
two entries have the same desktop-file id, the entry for the earlier (closer
to the top of the file) <AppDir> must be discarded. Next, add to the
pool the entries for any <AppDir>s specified by ancestor
<Menu> elements. If a parent menu has a duplicate entry (same
desktop-file id), the entry for the child menu has priority.
Next, walk through all <Include> and <Exclude> statements.
For each <Include>, match the rules against the pool of all desktop
entries. For each desktop entry that matches one of the rules,
add it to the menu to be displayed and mark it as having been allocated.
For each <Exclude>, match the rules against the currently-included
desktop entries. For each desktop entry that matches, remove it again
from the menu. Note that an entry that is included in a menu but excluded
again by a later <Exclude> is still considered allocated (for the
purposes of <OnlyUnallocated>) even though that entry no longer
appears in the menu.
Two passes are necessary, once for regular menus where any entry may
be matched, and once for <OnlyUnallocated> menus where only entries
which have not been marked as allocated may be matched.
The result is a tree of desktop entries, of course.
7 Legacy Menu Hierarchies #
Traditionally, menus were defined as a filesystem hierarchy, with each
filesystem directory corresponding to a submenu. Implementations of this
specification must be able to load these old-style hierarchies
as specified in this section.
The general approach is: the legacy hierarchy is converted into a
<Menu>, and then this menu layout is merged with the menu that
specified <LegacyDir>.
Desktop entries in the legacy hierarchy should be added to the pool of
desktop entries as if the <LegacyDir> were an
<AppDir>. Directory entries in the legacy hierarchy should be added
to the pool of directory entries as if the <LegacyDir> were a
<DirectoryDir>. This can be trivially implemented by adding
appropriate <AppDir> and <DirectoryDir> statements to the root
legacy <Menu>. There is one slight complexity, namely the
"prefix" attribute of <LegacyDir>.
The menu layout corresponds conceptually to the following, though actually
generating the XML is not necessary:
For each directory in the legacy hierarchy, a
<Menu> is created with the same <Name>
as the directory on disk.
This menu then contains an <Include> element that includes
each desktop entry in the directory. That is, it should have a
<Filename>Foo/Bar/foo.desktop</Filename>
for each desktop entry in the directory.
As a special exception, if a desktop entry in a directory contains
a Categories
field, that desktop entry should
not be included in the legacy menu.
That is, no <Include> element should be generated for
the entry. This allows a desktop entry to be installed
in a legacy location but still work optimally with the
menu system specified in this document.
If the legacy directory contains a ".directory" file, then
a <Directory> element should be generated that points to said
".directory" file.
Legacy desktop entries should not be assigned any
Categories
fields if they didn't have them
already, except that all legacy entries should have the
"Legacy" category added to allow menu files to treat them
specially. (If the same directory is given as both
a <LegacyDir> and an <AppDir>, its desktop
entries should be labeled "Legacy" only if the <LegacyDir>
appears later in the file than the <AppDir>.)
For example, say we have the following legacy directory hierarchy:
Conceptually that is converted to the following <Menu>:
This <Menu> is then merged as if it were in a file
and loaded with <MergeFile>.
A Registered Categories #
This section contains a number of well known categories and
suggestions on how to use them:
Note that category names are case-sensitive.
By including one of the Main Categories in an application's
desktop entry file, the application will be ensured that it will
show up in a section of the application menu dedicated to this
category. If multiple Main Categories are included in a single
desktop entry file, the entry may appear more than once in the
menu.
Category-based menus based on the Main Categories listed in this
specification do not provide a complete ontology for all
available applications. Category-based menu implementations
SHOULD therefore provide a "catch-all" submenu for applications
that cannot be appropriately placed elsewhere.
The table below lists all Main Categories.
A.2 Additional Categories #
The Related Categories column lists one or more categories that
are suggested to be used in conjunction with the Additional
Category. If the Related Categories column is blank, the
Additional Category can be used with any Main Category.
The table below describes Additional Categories.
A.3 Reserved Categories #
Reserved Categories have a desktop-specific meaning
that has not been standardized (yet). Desktop entry files that use
a reserved category MUST also include an appropriate OnlyShowIn= entry
to restrict themselves to those environments that properly support the
reserved category as used.
The table below describes Reserved Categories.
B Registered OnlyShowIn Environments #
Remember, these are case-sensitive. "KDE" not "kde" should be
used.
C Integrating your application in the menus #
The following steps describe how a third party application can add
menu items to the menu system:
Install desktop entries to
datadir/applications/ for each menu
item. Please namespace the filename, as in "vendor-foo.desktop", or
use a subdirectory of
datadir/applications/ so you have
"vendor/foo.desktop." Please be sure all desktop entries are valid
(see the
desktop-file-utils (http://www.freedesktop.org/software/desktop-file-utils/) package for a validation utility).
Install an XML menu file to sysconfdir/menus/applications-merged/ to add any submenus, if your desktop entries aren't already
included in some common categories.
Install any directory entries needed for your submenus to datadir/desktop-directories/, taking care to namespace and validate
the directory entries.
If an application is intended to be installed by root on a system wide
basis then /usr/share is recommended to be used as value for
datadir and /etc/xdg is recommended to be
used as value for sysconfdir.
In case the /usr/share hierarchy is not writable it is recommended to
use /usr/local/share as value for datadir
instead.
If an application is intended to be installed by an unprivileged user
for exclusive use by that user only then
$XDG_DATA_HOME
should be used as value
for datadir and
$XDG_CONFIG_HOME
should be used as value
for sysconfdir.
If $XDG_DATA_HOME
is not set, the default value of
$HOME/.local/share should be used for it.
If $XDG_CONFIG_HOME
is not set, the default value of
$HOME/.config should be used for it.
C.4 Backward Compatibility #
For a limited time, installing a directory hierarchy to
the old GNOME/KDE specific locations such as /usr/share/applnk and
/usr/share/gnome/apps will continue to work as way to add your
application to the menu system as well. There are two ways to support
both the old and new menu systems at the same time:
If you add a Categories
line to the desktop
entries in the legacy hierarchy, implementations of this
specification will ignore their location in the legacy hierarchy,
and arrange them according to Categories
instead.
This allows you to install a single desktop file that works in all
cases, though on the down side it's in a legacy location.
If you add the line OnlyShowIn=Old;
to a desktop
entry, then old legacy implementations that ignore
OnlyShowIn
will still show the desktop entry, but
implementations of this specification will not. Thus you can
add an "OnlyShowIn=Old;
" entry to the legacy
hierarchy, and a new-style desktop entry to
datadir/applications/, and still get
only one entry in the menus.
This glossary defines some of the terms used in this specification.
- Desktop entry #
A desktop entry is a file with a name ending in the ".desktop"
extension which conforms to the desktop
entry specification (http://www.freedesktop.org/Standards/desktop-entry-spec) with Type=Application
.
It describes a menu item, including a name, an icon, and what to do when the item is selected.
Desktop entries are also known as ".desktop files."
- Desktop-File Id #
The ID to identify a desktop entry with.
For desktop files installed in $XDG_DATA_DIRS/applications, this
is the same as the desktop file ID defined in the Desktop Entry Specification.
In addition, if /opt/ude
is defined
as <LegacyDir prefix="foo-"> then
/opt/ude/Settings/bar.desktop
has
the desktop-file id foo-bar.desktop
- Directory entry #
A directory entry is a file with a name ending in the ".directory"
extension which conforms to the desktop
entry specification (http://www.freedesktop.org/Standards/desktop-entry-spec) with Type=Directory
.
It provides a localized name and an icon for a submenu.
Directory entries are also known as ".directory files."
A "menu path" is the path to a particular menu. Menu paths are
always "relative" so never start with a slash character.
The path to a menu is simply the <Name> of each parent
of the menu, followed by the <Name> of the menu itself.
For example, "Foo/Bar/Baz" is a valid menu path.
- Relative path #
The canonical path to a directory entry, relative to the
<DirectoryDir> containing the
entry. For example, if /usr/share/desktop-directories
is
specified as an <DirectoryDir>, the relative path to
/usr/share/desktop-directories/foo/bar.directory
is
foo/bar.directory
.