931 lines
77 KiB
HTML
931 lines
77 KiB
HTML
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|||
|
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>Desktop Menu Specification</title><meta name="generator" content="DocBook XSL Stylesheets V1.64.1" /><link rel="home" href="#index" title="Desktop Menu Specification" /><link rel="next" href="#introduction" title="Introduction" /></head><body><div class="article" lang="en" xml:lang="en"><div class="titlepage"><div><div><h1 class="title"><a id="id2392226"></a>Desktop Menu Specification</h1></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">Waldo</span> <span class="surname">Bastian</span></h3><div class="affiliation"><div class="address"><p><br />
|
|||
|
<tt class="email"><<a href="mailto:bastian@kde.org">bastian@kde.org</a>></tt><br />
|
|||
|
</p></div></div></div><div class="author"><h3 class="author"><span class="firstname">Francois</span> <span class="surname">Gouget</span></h3><div class="affiliation"><div class="address"><p><br />
|
|||
|
<tt class="email"><<a href="mailto:fgouget@codeweavers.com">fgouget@codeweavers.com</a>></tt><br />
|
|||
|
</p></div></div></div><div class="author"><h3 class="author"><span class="firstname">Alex</span> <span class="surname">Graveley</span></h3><div class="affiliation"><div class="address"><p><br />
|
|||
|
<tt class="email"><<a href="mailto:alex@ximian.com">alex@ximian.com</a>></tt><br />
|
|||
|
</p></div></div></div><div class="author"><h3 class="author"><span class="firstname">George</span> <span class="surname">Lebl</span></h3><div class="affiliation"><div class="address"><p><br />
|
|||
|
<tt class="email"><<a href="mailto:jirka@5z.com">jirka@5z.com</a>></tt><br />
|
|||
|
</p></div></div></div><div class="author"><h3 class="author"><span class="firstname">Havoc</span> <span class="surname">Pennington</span></h3><div class="affiliation"><div class="address"><p><br />
|
|||
|
<tt class="email"><<a href="mailto:hp@pobox.com">hp@pobox.com</a>></tt><br />
|
|||
|
</p></div></div></div><div class="author"><h3 class="author"><span class="firstname">Heinrich</span> <span class="surname">Wendel</span></h3><div class="affiliation"><div class="address"><p><br />
|
|||
|
<tt class="email"><<a href="mailto:h_wendel@cojobo.net">h_wendel@cojobo.net</a>></tt><br />
|
|||
|
</p></div></div></div></div></div><div><p class="releaseinfo">Version 0.8</p></div></div><div></div><hr /></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#introduction">Introduction</a></span></dt><dt><span class="sect1"><a href="#paths">File locations</a></span></dt><dt><span class="sect1"><a href="#desktop-entry-extensions">Extensions to the desktop entry format</a></span></dt><dd><dl><dt><span class="sect2"><a href="#desktop-entry-extensions-examples">Examples of using Categories and OnlyShowIn</a></span></dt></dl></dd><dt><span class="sect1"><a href="#menu-file-format">Format of menu files</a></span></dt><dd><dl><dt><span class="sect2"><a href="#menu-file-doctype">Doctype Declaration</a></span></dt><dt><span class="sect2"><a href="#menu-file-elements">Elements</a></span></dt></dl></dd><dt><span class="sect1"><a href="#merge-algorithm">Merging</a></span></dt><dt><span class="sect1"><a href="#query-algorithm">Generating the menus</a></span></dt><dt><span class="sect1"><a href="#legacy-hierarchies">Legacy Menu Hierarchies</a></span></dt><dt><span class="sect1"><a href="#example">Example Menu File</a></span></dt><dt><span class="appendix"><a href="#category-registry">A. Registered Categories</a></span></dt><dt><span class="appendix"><a href="#onlyshowin-registry">B. Registered OnlyShowIn Environments</a></span></dt><dt><span class="appendix"><a href="#third-party-howto">C. How to add your application to the menus</a></span></dt><dt><span class="appendix"><a href="#implementation-notes">D. Implementation notes</a></span></dt><dd><dl><dt><span class="sect1"><a href="#menu-editing">Menu editing</a></span></dt></dl></dd><dt><span class="glossary"><a href="#id2506596">Glossary</a></span></dt></dl></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="introduction"></a>Introduction</h2></div></div><div></div></div><p>
|
|||
|
This DRAFT 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.
|
|||
|
</p><p>
|
|||
|
The basic scheme is very simple. Information about each application (menu
|
|||
|
item) is stored in a desktop entry (see <a href="http://www.freedesktop.org/standards/desktop-entry-spec" target="_top">Desktop
|
|||
|
Entry Standard</a>). Then an XML configuration file defines the
|
|||
|
hierarchical arrangement (layout) of menu items, and which menu items are
|
|||
|
actually displayed.
|
|||
|
</p><p>
|
|||
|
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
|
|||
|
<i class="firstterm">merging</i> two menu layouts.
|
|||
|
</p><p>
|
|||
|
In addition to a strict definition of the contents of each menu this
|
|||
|
specification also forsees in a number of layout / presentation hints.
|
|||
|
This part of the specification is optional, implementations may chose to
|
|||
|
ignore these hints.
|
|||
|
</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="paths"></a>File locations</h2></div></div><div></div></div><p>
|
|||
|
Files involved in this specification are located according to the "desktop
|
|||
|
base directory specification" which can be found on <a href="http://www.freedesktop.org/standards/" target="_top">www.freedesktop.org</a>.
|
|||
|
</p><p>
|
|||
|
Here are the files defined by this specification:
|
|||
|
</p><div class="variablelist"><dl><dt><span class="term"><tt class="varname">$XDG_CONFIG_DIRS</tt>/menus/applications.menu</span></dt><dd><p>
|
|||
|
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 applications.menu, it replaces the systemwide one.
|
|||
|
(Though the user's menu may explicitly merge the systemwide one.)
|
|||
|
</p><p>
|
|||
|
Other menu files may exist, but are not specified in this
|
|||
|
document.
|
|||
|
</p></dd><dt><span class="term"><tt class="varname">$XDG_CONFIG_DIRS</tt>/menus/<i class="replaceable"><tt>menu-file-basename</tt></i>-merged/</span></dt><dd><p>
|
|||
|
The default merge directories included in the
|
|||
|
<DefaultMergeDirs> element. By convention, third parties
|
|||
|
may add new <Menu> files in this
|
|||
|
location. <i class="replaceable"><tt>menu-file-basename</tt></i> means the
|
|||
|
"applications" from "applications.menu" for example. So the merge
|
|||
|
directory would be "applications-merged".
|
|||
|
</p></dd><dt><span class="term"><tt class="varname">$XDG_DATA_DIRS</tt>/applications/</span></dt><dd><p>
|
|||
|
This directory contains a .desktop file for each possible menu
|
|||
|
item. Each directory in the <tt class="varname">$XDG_DATA_DIRS</tt>
|
|||
|
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.
|
|||
|
</p><p>
|
|||
|
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.
|
|||
|
</p></dd><dt><span class="term"><tt class="varname">$XDG_DATA_DIRS</tt>/desktop-directories/</span></dt><dd><p>
|
|||
|
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.
|
|||
|
</p><p>
|
|||
|
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.
|
|||
|
</p></dd></dl></div><p>
|
|||
|
</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="desktop-entry-extensions"></a>Extensions to the desktop entry format</h2></div></div><div></div></div><p>
|
|||
|
This specification adds two new fields to <a href="http://www.freedesktop.org/standards/desktop-entry-spec" target="_top">desktop
|
|||
|
entries</a>: <tt class="varname">Categories</tt>,
|
|||
|
<tt class="varname">OnlyShowIn</tt> and <tt class="varname">NotShowIn</tt>.
|
|||
|
</p><p>
|
|||
|
The <tt class="varname">Categories</tt> field is a list of strings used to
|
|||
|
classify menu items. For example, applications in the
|
|||
|
<tt class="literal">AudioVideo</tt> category might end up in the "Sound &
|
|||
|
Video" submenu. <a href="#category-registry" title="A. Registered Categories">Appendix A, <i>Registered Categories</i></a> 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.
|
|||
|
</p><p>
|
|||
|
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.
|
|||
|
</p><p>
|
|||
|
The <tt class="varname">OnlyShowIn</tt> field is a list of strings identifying
|
|||
|
the environments that should display a given menu item. If an
|
|||
|
<tt class="varname">OnlyShowIn</tt> 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. <a href="#onlyshowin-registry" title="B. Registered OnlyShowIn Environments">Appendix B, <i>Registered OnlyShowIn Environments</i></a> enumerates the strings to use for
|
|||
|
some common environments.
|
|||
|
</p><p>
|
|||
|
The <tt class="varname">NotShowIn</tt> field is a list of strings identifying
|
|||
|
the environments that should not display a given menu item. If an
|
|||
|
<tt class="varname">NotShowIn</tt> 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. <a href="#onlyshowin-registry" title="B. Registered OnlyShowIn Environments">Appendix B, <i>Registered OnlyShowIn Environments</i></a> enumerates the strings to use for
|
|||
|
some common environments.
|
|||
|
</p><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="desktop-entry-extensions-examples"></a>Examples of using <tt class="varname">Categories</tt> and <tt class="varname">OnlyShowIn</tt></h3></div></div><div></div></div><p>
|
|||
|
A desktop entry for a Qt-based image viewer might contain
|
|||
|
this <tt class="varname">Categories</tt> line:
|
|||
|
</p><div class="informalexample"><pre class="programlisting">
|
|||
|
Categories=Qt;Graphics;RasterGraphics;Viewer;
|
|||
|
</pre></div><p>
|
|||
|
</p><p>
|
|||
|
A desktop entry for Octave, a command-line mathematics program (which
|
|||
|
would also have the field <tt class="literal">Terminal=true</tt>), might have:
|
|||
|
</p><div class="informalexample"><pre class="programlisting">
|
|||
|
Categories=ConsoleOnly;Math;
|
|||
|
</pre></div><p>
|
|||
|
</p><p>
|
|||
|
A desktop entry for a GNOME-specific calculator program
|
|||
|
that should only appear in GNOME might have:
|
|||
|
</p><div class="informalexample"><pre class="programlisting">
|
|||
|
Categories=GNOME;Utility;
|
|||
|
OnlyShowIn=GNOME;
|
|||
|
</pre></div><p>
|
|||
|
Note that the <tt class="varname">OnlyShowIn</tt> field is a
|
|||
|
<span class="emphasis"><em>list</em></span> and thus ends in a semicolon.
|
|||
|
</p></div></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="menu-file-format"></a>Format of menu files</h2></div></div><div></div></div><p>
|
|||
|
Menu files must be well-formed XML files, conform to the menu file DTD,
|
|||
|
and end in the extension ".menu". DTD conformance implies that
|
|||
|
implementation-specific extensions to the file format are not allowed;
|
|||
|
implementations are expected to stop processing if they encounter XML
|
|||
|
elements or attributes that are not specified in this document.
|
|||
|
</p><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="menu-file-doctype"></a>Doctype Declaration</h3></div></div><div></div></div><p>
|
|||
|
Menu files for this version of the specification must use the following
|
|||
|
namespace, public and system identifiers:
|
|||
|
</p><div class="variablelist"><dl><dt><span class="term">Namespace</span></dt><dd><p>
|
|||
|
<tt class="literal">http://www.freedesktop.org/standards/menu</tt>
|
|||
|
</p></dd><dt><span class="term">Public Identifier for 0.8</span></dt><dd><p>
|
|||
|
<tt class="literal">PUBLIC "-//freedesktop//DTD Menu 0.8//EN"</tt>
|
|||
|
</p></dd><dt><span class="term">System Identifier for 0.8</span></dt><dd><p>
|
|||
|
<tt class="literal">http://www.freedesktop.org/standards/menu-spec/menu-0.8.dtd</tt>
|
|||
|
</p></dd></dl></div><p>
|
|||
|
|
|||
|
Here is a sample doctype declaration:
|
|||
|
</p><div class="informalexample"><pre class="programlisting">
|
|||
|
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 0.8//EN"
|
|||
|
"http://www.freedesktop.org/standards/menu-spec/menu-0.8.dtd">
|
|||
|
</pre></div><p>
|
|||
|
|
|||
|
All menu files MUST include the doctype declaration, so that
|
|||
|
implementations can adapt to different versions of this specification
|
|||
|
(and so implementations can validate the menu file against
|
|||
|
the DTD).
|
|||
|
</p></div><div class="sect2" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 class="title"><a id="menu-file-elements"></a>Elements</h3></div></div><div></div></div><p>
|
|||
|
</p><div class="variablelist"><dl><dt><span class="term"><Menu></span></dt><dd><p>
|
|||
|
The root element is <Menu>. Each <Menu> element may
|
|||
|
contain any number of nested <Menu> elements, indicating submenus.
|
|||
|
</p></dd><dt><span class="term"><AppDir></span></dt><dd><p>
|
|||
|
This element may only appear below <Menu>. The
|
|||
|
content of this element is a directory name. Desktop entries
|
|||
|
in this directory are scanned and added to the pool of entries
|
|||
|
which can be included in this <Menu> and its submenus.
|
|||
|
Only files ending in ".desktop" should be used, other files are
|
|||
|
ignored.
|
|||
|
</p><p>
|
|||
|
Desktop entries in the pool of available entries are identified
|
|||
|
by their <i class="firstterm">desktop-file id</i> (see <a href="#term-desktop-file-id">Desktop-File Id</a>).
|
|||
|
The desktop-file id of a desktop entry is equal to its filename,
|
|||
|
with any path components removed.
|
|||
|
So given a <AppDir>
|
|||
|
<tt class="filename">/foo/bar</tt> and desktop entry
|
|||
|
<tt class="filename">/foo/bar/Hello.desktop</tt> the desktop
|
|||
|
entry would get a desktop-file id of <tt class="filename">Hello.desktop</tt>
|
|||
|
</p><p>
|
|||
|
If the directory contains sub-directories then these sub-directories
|
|||
|
should be (recursively) scanned as well. The name of the subdirectory
|
|||
|
should be added as prefix to the desktop-file id together with a dash character ("-")
|
|||
|
So given a <AppDir>
|
|||
|
<tt class="filename">/foo/bar</tt> and desktop entry
|
|||
|
<tt class="filename">/foo/bar/booz/Hello.desktop</tt> the desktop
|
|||
|
entry would get a desktop-file id of <tt class="filename">booz-Hello.desktop</tt>
|
|||
|
A desktop entry <tt class="filename">/foo/bar/bo/oz/Hello.desktop</tt> would result
|
|||
|
in a desktop-file id of <tt class="filename">bo-oz-Hello.desktop</tt>
|
|||
|
</p><p>
|
|||
|
<AppDir> elements appearing later in the menu file have
|
|||
|
priority in case of collisions between desktop-file ids.
|
|||
|
</p><p>
|
|||
|
If the filename given as an <AppDir> is not an absolute
|
|||
|
path, it should be located relative to the location of the menu
|
|||
|
file being parsed.
|
|||
|
</p><p>
|
|||
|
Duplicate <AppDir> elements (that specify the same
|
|||
|
directory) should be ignored, but the <span class="emphasis"><em>last</em></span>
|
|||
|
duplicate in the file should be used when establishing the order
|
|||
|
in which to scan the directories. This is important when merging
|
|||
|
(see <a href="#merge-algorithm" title="Merging">the section called “Merging”</a>). The order of
|
|||
|
<AppDir> elements with respect to <Include> and
|
|||
|
<Exclude> elements is not relevant, also to facilitate
|
|||
|
merging.
|
|||
|
</p></dd><dt><span class="term"><DefaultAppDirs></span></dt><dd><p>
|
|||
|
This element may only appear below <Menu>. The element has
|
|||
|
no content. The element should be treated as if it were a list
|
|||
|
of <AppDir> elements containing the default app dir
|
|||
|
locations
|
|||
|
(<i class="replaceable"><tt>datadir</tt></i>/applications/ etc.). When expanding
|
|||
|
<DefaultAppDirs> to a list of <AppDir>, the default
|
|||
|
locations that are earlier in the search path go later in the
|
|||
|
<Menu> so that they have priority.
|
|||
|
</p></dd><dt><span class="term"><DirectoryDir></span></dt><dd><p>
|
|||
|
This element may only appear below <Menu>. The content of
|
|||
|
this element is a directory name. Each directory listed in a
|
|||
|
<DirectoryDir> element will be searched for directory
|
|||
|
entries to be used when resolving the <Directory> element
|
|||
|
for this menu and its submenus.
|
|||
|
If the filename given as a <DirectoryDir> is not an absolute path,
|
|||
|
it should be located relative to the location
|
|||
|
of the menu file being parsed.
|
|||
|
</p><p>
|
|||
|
Directory entries in the pool of available entries are identified
|
|||
|
by their <i class="firstterm">relative path</i> (see <a href="#term-relative-path">Relative path</a>).
|
|||
|
</p><p>
|
|||
|
If two directory entries have duplicate relative paths, the one from
|
|||
|
the last (furthest down) element in the menu file must be used.
|
|||
|
Only files ending in the extension ".directory" should be
|
|||
|
loaded, other files should be ignored.
|
|||
|
</p><p>
|
|||
|
Duplicate <DirectoryDir> elements (that specify the same
|
|||
|
directory) are handled as with duplicate <AppDir>
|
|||
|
elements (the last duplicate is used).
|
|||
|
</p></dd><dt><span class="term"><DefaultDirectoryDirs></span></dt><dd><p>
|
|||
|
This element may only appear below <Menu>. The element has
|
|||
|
no content. The element should be treated as if it were a list
|
|||
|
of <DirectoryDir> elements containing the default desktop dir
|
|||
|
locations
|
|||
|
(<i class="replaceable"><tt>datadir</tt></i>/desktop-directories/ etc.). The default
|
|||
|
locations that are earlier in the search path go later in the
|
|||
|
<Menu> so that they have priority.
|
|||
|
</p></dd><dt><span class="term"><Name></span></dt><dd><p>
|
|||
|
Each <Menu> element must have a single <Name>
|
|||
|
element. The content of the <Name> element is a name to
|
|||
|
be used when referring to the given menu. Each submenu of a
|
|||
|
given <Menu> must have a unique name. <Menu>
|
|||
|
elements can thus be referenced by a menu path, for example
|
|||
|
"Applications/Graphics." The <Name> field must not contain
|
|||
|
the slash character ("/"); implementations should discard
|
|||
|
any name containing a slash. See also <a href="#term-menu-path">Menu path</a>.
|
|||
|
</p></dd><dt><span class="term"><Directory></span></dt><dd><p>
|
|||
|
Each <Menu> element has any number of <Directory>
|
|||
|
elements. The content of the <Directory> element
|
|||
|
is the relative path of a directory entry containing metainformation
|
|||
|
about the <Menu>, such as its icon and localized name.
|
|||
|
If no <Directory> is specified for a <Menu>,
|
|||
|
its <Name> field should be used as the user-visible
|
|||
|
name of the menu.
|
|||
|
</p><p>
|
|||
|
Duplicate <Directory> elements are allowed in order
|
|||
|
to simplify menu merging, and allow user menus to override
|
|||
|
system menus. The last <Directory> element to appear
|
|||
|
in the menu file "wins" and other elements are ignored,
|
|||
|
unless the last element points to a nonexistent directory
|
|||
|
entry, in which case the previous element should be tried instead,
|
|||
|
and so on.
|
|||
|
</p></dd><dt><span class="term"><OnlyUnallocated> and <NotOnlyUnallocated></span></dt><dd><p>
|
|||
|
Each <Menu> may contain any number of
|
|||
|
<OnlyUnallocated> and <NotOnlyUnallocated>
|
|||
|
elements. Only the last such element to appear is relevant, as
|
|||
|
it determines whether the <Menu> can contain any desktop
|
|||
|
entries, or only those desktop entries that do not match other
|
|||
|
menus. If neither <OnlyUnallocated> nor
|
|||
|
<NotOnlyUnallocated> elements are present, the default
|
|||
|
is <NotOnlyUnallocated>.
|
|||
|
</p><p>
|
|||
|
To handle <OnlyUnallocated>, the menu file must be
|
|||
|
analyzed in two conceptual passes. The first pass processes
|
|||
|
<Menu> elements that can match any desktop entry. During
|
|||
|
this pass, each desktop entry is marked according to whether it
|
|||
|
was included in some <Menu>. The second pass processes
|
|||
|
only <Menu> elements that are restricted to unallocated
|
|||
|
desktop entries. During the second pass, queries may only match
|
|||
|
desktop entries that were not allocated to some menu during the
|
|||
|
first pass. See <a href="#query-algorithm" title="Generating the menus">the section called “Generating the menus”</a>.
|
|||
|
</p></dd><dt><span class="term"><Deleted> and <NotDeleted></span></dt><dd><p>
|
|||
|
Each <Menu> may contain any number of <Deleted> and
|
|||
|
<NotDeleted> elements. Only the last such element to
|
|||
|
appear is relevant, as it determines whether the <Menu>
|
|||
|
has been deleted. If neither <Deleted> nor
|
|||
|
<NotDeleted> elements are present, the default is
|
|||
|
<NotDeleted>. The purpose of this element is to support
|
|||
|
menu editing. If a menu contains a <Deleted> element
|
|||
|
not followed by a <NotDeleted> element, that menu
|
|||
|
should be ignored.
|
|||
|
</p></dd><dt><span class="term"><Include></span></dt><dd><p>
|
|||
|
An <Include> element is a set of rules attempting to match
|
|||
|
some of the known desktop entries. The <Include> element
|
|||
|
contains a list of any number of matching rules. Matching rules
|
|||
|
are specified using the elements <And>, <Or>,
|
|||
|
<Not>, <All>, <Filename>, and
|
|||
|
<Category>. Each rule in a list of rules has a logical OR
|
|||
|
relationship, that is, desktop entries which match any rule
|
|||
|
are included in the menu.
|
|||
|
</p><p>
|
|||
|
<Include> elements must appear immediately under
|
|||
|
<Menu> elements. The desktop entries they match are
|
|||
|
included in the menu. <Include> and <Exclude>
|
|||
|
elements for a given <Menu> are processed in order,
|
|||
|
with queries earlier in the file handled first. This has
|
|||
|
implications for merging, see <a href="#merge-algorithm" title="Merging">the section called “Merging”</a>.
|
|||
|
See <a href="#query-algorithm" title="Generating the menus">the section called “Generating the menus”</a> for full details on
|
|||
|
how to process <Include> and <Exclude> elements.
|
|||
|
</p></dd><dt><span class="term"><Exclude></span></dt><dd><p>
|
|||
|
Any number of <Exclude> elements may appear below a
|
|||
|
<Menu> element. The content of an <Exclude> element
|
|||
|
is a list of matching rules, just as with an
|
|||
|
<Include>. However, the desktop entries matched are
|
|||
|
removed from the list of desktop entries included so far. (Thus
|
|||
|
an <Exclude> element that appears before any
|
|||
|
<Include> elements will have no effect, for example, as no
|
|||
|
desktop entries have been included yet.)
|
|||
|
</p></dd><dt><span class="term"><Filename></span></dt><dd><p>
|
|||
|
The <Filename> element is the most basic matching rule.
|
|||
|
It matches a desktop entry if the desktop entry has the given
|
|||
|
desktop-file id. See <a href="#term-desktop-file-id">Desktop-File Id</a>.
|
|||
|
</p></dd><dt><span class="term"><Category></span></dt><dd><p>
|
|||
|
The <Category> element is another basic matching
|
|||
|
predicate. It matches a desktop entry if the desktop entry has
|
|||
|
the given category in its <tt class="varname">Categories</tt> field.
|
|||
|
</p></dd><dt><span class="term"><All></span></dt><dd><p>
|
|||
|
The <All> element is a matching rule that matches
|
|||
|
all desktop entries.
|
|||
|
</p></dd><dt><span class="term"><And></span></dt><dd><p>
|
|||
|
The <And> element contains a list of matching rules.
|
|||
|
If each of the matching rules inside the <And>
|
|||
|
element match a desktop entry, then the entire
|
|||
|
<And> rule matches the desktop entry.
|
|||
|
</p></dd><dt><span class="term"><Or></span></dt><dd><p>
|
|||
|
The <Or> element contains a list of matching rules.
|
|||
|
If any of the matching rules inside the <Or>
|
|||
|
element match a desktop entry, then the entire
|
|||
|
<Or> rule matches the desktop entry.
|
|||
|
</p></dd><dt><span class="term"><Not></span></dt><dd><p>
|
|||
|
The <Not> element contains a list of matching rules. If
|
|||
|
any of the matching rules inside the <Not> element matches
|
|||
|
a desktop entry, then the entire <Not> rule does
|
|||
|
<span class="emphasis"><em>not</em></span> match the desktop entry. That is,
|
|||
|
matching rules below <Not> have a logical OR relationship.
|
|||
|
</p></dd><dt><span class="term"><MergeFile></span></dt><dd><p>
|
|||
|
Any number of <MergeFile> elements may be listed below a
|
|||
|
<Menu> element, giving the name of another menu file to
|
|||
|
be merged into this one. <a href="#merge-algorithm" title="Merging">the section called “Merging”</a>
|
|||
|
specifies how merging is done. The root <Menu> of the
|
|||
|
merged file will be merged into the immediate parent of the
|
|||
|
<MergeFile> element. The <Name> element of the
|
|||
|
root <Menu> of the merged file are ignored. If the
|
|||
|
filename given as a <MergeFile> is not an absolute path,
|
|||
|
it should be located relative to the location of the menu file
|
|||
|
being parsed.
|
|||
|
</p><p>
|
|||
|
Duplicate <MergeFile> elements (that specify the same
|
|||
|
file) are handled as with duplicate <AppDir>
|
|||
|
elements (the last duplicate is used).
|
|||
|
</p></dd><dt><span class="term"><MergeDir></span></dt><dd><p>
|
|||
|
Any number of <MergeDir> elements may be listed below a
|
|||
|
<Menu> element. A <MergeDir> contains the name of a
|
|||
|
directory. Each file in the given directory which ends in the
|
|||
|
".menu" extension should be merged in the same way that a
|
|||
|
<MergeFile> would be. If the filename given as a
|
|||
|
<MergeDir> is not an absolute path, it should be located
|
|||
|
relative to the location of the menu file being parsed.
|
|||
|
The files inside the merged directory are not merged in any
|
|||
|
specified order.
|
|||
|
</p><p>
|
|||
|
Duplicate <MergeDir> elements (that specify the same
|
|||
|
directory) are handled as with duplicate <AppDir>
|
|||
|
elements (the last duplicate is used).
|
|||
|
</p></dd><dt><span class="term"><DefaultMergeDirs></span></dt><dd><p>
|
|||
|
This element may only appear below <Menu>. The element has
|
|||
|
no content. The element should be treated as if it were a list
|
|||
|
of <MergeDir> elements containing the default merge
|
|||
|
directory locations. When expanding <DefaultMergeDirs> to a
|
|||
|
list of <MergeDir>, the default locations that are earlier
|
|||
|
in the search path go later in the <Menu> so that they
|
|||
|
have priority.
|
|||
|
</p></dd><dt><span class="term"><LegacyDir></span></dt><dd><p>
|
|||
|
This element may only appear below <Menu>. The text
|
|||
|
content of this element is a directory name. Each directory
|
|||
|
listed in a <LegacyDir> element will be an old-style
|
|||
|
legacy hierarchy of desktop entries, see <a href="#legacy-hierarchies" title="Legacy Menu Hierarchies">the section called “Legacy Menu Hierarchies”</a> for how to load such a
|
|||
|
hierarchy. Implementations must not load legacy hierarchies that
|
|||
|
are not explicitly specified in the menu file (because for
|
|||
|
example the menu file may not be the main menu). If the
|
|||
|
filename given as a <LegacyDir> is not an absolute path,
|
|||
|
it should be located relative to the location of the menu file
|
|||
|
being parsed.
|
|||
|
</p><p>
|
|||
|
Duplicate <LegacyDir> elements (that specify the same
|
|||
|
directory) are handled as with duplicate <AppDir>
|
|||
|
elements (the last duplicate is used).
|
|||
|
</p><p>
|
|||
|
The <LegacyDir> element may have one attribute,
|
|||
|
<tt class="literal">prefix</tt>. Normally, given a <LegacyDir>
|
|||
|
<tt class="filename">/foo/bar</tt> and desktop entry
|
|||
|
<tt class="filename">/foo/bar/baz/Hello.desktop</tt> the desktop
|
|||
|
entry would get a desktop-file id of <tt class="filename">Hello.desktop</tt>.
|
|||
|
Given a prefix of <tt class="literal">boo-</tt>, it would instead be
|
|||
|
assigned the desktop-file id <tt class="filename">boo-Hello.desktop</tt>.
|
|||
|
The prefix should not contain path separator ('/') characters.
|
|||
|
</p></dd><dt><span class="term"><KDELegacyDirs></span></dt><dd><p>
|
|||
|
This element may only appear below <Menu>. The element has
|
|||
|
no content. The element should be treated as if it were a list
|
|||
|
of <LegacyDir> elements containing the traditional desktop
|
|||
|
file locations supported by KDE with a hard coded prefix of "kde-".
|
|||
|
When expanding <KDELegacyDirs> to a list of <LegacyDir>, the
|
|||
|
locations that are earlier in the search path go later in the
|
|||
|
<Menu> so that they have priority.
|
|||
|
The search path can be obtained by running <tt class="filename">kde-config --path apps</tt>
|
|||
|
</p></dd><dt><span class="term"><Move></span></dt><dd><p>
|
|||
|
This element may only appear below <Menu>. The
|
|||
|
<Move> element contains pairs of <Old>/<New>
|
|||
|
elements indicating how to rename a descendant of the current
|
|||
|
<Menu>. If the destination path already exists, the moved
|
|||
|
menu is merged with the destination menu (see <a href="#merge-algorithm" title="Merging">the section called “Merging”</a> for details).
|
|||
|
</p><p>
|
|||
|
<Move> is used primarily to fix up legacy directories.
|
|||
|
For example, say you are merging a <LegacyDir> with folder
|
|||
|
names that don't match the current hierarchy; the legacy folder
|
|||
|
names can be moved to the new names, where they will be merged
|
|||
|
with the new folders.
|
|||
|
</p><p>
|
|||
|
<Move> may or may not be useful for implementing menu
|
|||
|
editing, see <a href="#menu-editing" title="Menu editing">the section called “Menu editing”</a>.
|
|||
|
</p><p>
|
|||
|
Duplicate <Move> elements are merged as specified in <a href="#merge-algorithm" title="Merging">the section called “Merging”</a>. Note that duplicates (two moves of
|
|||
|
the same path) can be detected easily because of the following
|
|||
|
rule: a move must reside at the lowest possible point.
|
|||
|
</p><p>
|
|||
|
In other words, all moves have exactly one permissible location
|
|||
|
in the <Menu> hierarchy. Implementations can trivially
|
|||
|
detect violations of this rule: the <Old> and <New>
|
|||
|
paths may never share a common prefix. Moving "Foo/Bar" to
|
|||
|
"Foo/Baz" must be done with a <Move> element that's a
|
|||
|
child of the "Foo" <Menu>, i.e. by moving "Bar" to "Baz", not
|
|||
|
by moving "Foo/Bar" to "Foo/Baz".
|
|||
|
</p></dd><dt><span class="term"><Old></span></dt><dd><p>
|
|||
|
This element may only appear below <Move>, and
|
|||
|
must be followed by a <New> element. The content of both
|
|||
|
<Old> and <New> should be a menu path
|
|||
|
(slash-separated concatenation of <Name> fields, see
|
|||
|
<a href="#term-menu-path">Menu path</a>).
|
|||
|
Paths are interpreted relative to the menu containing
|
|||
|
the <Move> element.
|
|||
|
</p></dd><dt><span class="term"><New></span></dt><dd><p>
|
|||
|
This element may only appear below <Move>, and must
|
|||
|
be preceded by an <Old> element. The <New> element
|
|||
|
specifies the new path for the preceding <Old> element.
|
|||
|
</p></dd><dt><span class="term"><Layout></span></dt><dd><p>
|
|||
|
The <Layout> element is an optional part of this specification.
|
|||
|
Implementations that do not support the <Layout> element should
|
|||
|
preserve any <Layout> elements and their contents as far as
|
|||
|
possible.
|
|||
|
Each <Menu> may optionally contain a <Layout> element.
|
|||
|
If multipe elements appear then only the last such element is relevant.
|
|||
|
The purpose of this element is to offer suggestions for the presentation
|
|||
|
of the menu.
|
|||
|
If a menu does not contain a <Layout> element or if it contains
|
|||
|
an empty <Layout> element then the default layout should be used.
|
|||
|
The <Layout> element may contain <Filename>, <Menuname>,
|
|||
|
<Separator> and <Merge> elements. The <Layout> element
|
|||
|
defines a suggested layout for the menu starting from top to bottom.
|
|||
|
References to desktop entries that are not contained in this
|
|||
|
menu as defined by the <Include> and <Exclude> elements should
|
|||
|
be ignored. References to sub-menus that are not directly contained in this
|
|||
|
menu as defined by the <Menu> elements should be ignored.
|
|||
|
</p></dd><dt><span class="term"><DefaultLayout [show_empty="false"] [inline="false"] [inline_limit="4"] [inline_header="true"] [inline_alias="false"]></span></dt><dd><p>
|
|||
|
The <DefaultLayout> element is an optional part of this specification.
|
|||
|
Implementations that do not support the <DefaultLayout> element should
|
|||
|
preserve any <DefaultLayout> elements and their contents as far as
|
|||
|
possible.
|
|||
|
Each <Menu> may optionally contain a <DefaultLayout> element
|
|||
|
which defines the default-layout for the current menu and all its sub-menus.
|
|||
|
If a menu has a <DefaultLayout> element then this will override
|
|||
|
any default-layout specified by a parent menu.
|
|||
|
The default-layout defines the suggested layout if a <Menu> element
|
|||
|
does either not have <Layout> element or if it has an empty <Layout> element.
|
|||
|
For explanations of the various attributes see the <Menuname> element.
|
|||
|
If no default-layout has been specified then the layout as specified by the following
|
|||
|
elements should be assumed:
|
|||
|
<DefaultLayout show_empty="false" inline="false" inline_limit="4" inline_header="true" inline_alias="false"><Merge type="menus"/><Merge type="files"/></DefaultLayout>
|
|||
|
</p></dd><dt><span class="term"><Menuname [show_empty="..."] [inline="..."] [inline_limit="..."] [inline_header="..."] [inline_alias="..."]></span></dt><dd><p>
|
|||
|
This element may only appear as a child of a <Layout> or <DefaultLayout>
|
|||
|
menu. Its contents references an immediate sub-menu of the current menu as defined
|
|||
|
with the <Menu> element, as such it should never contain a slash.
|
|||
|
If no such sub-menu exists the element should be ignored.
|
|||
|
This element may have various attributes, the default values are taken from the DefaultLayout key.
|
|||
|
The show_empty attribute defines whether a menu that contains no desktop
|
|||
|
entries and no sub-menus should be shown at all. The show_empty attribute
|
|||
|
can be "true" or "false".
|
|||
|
It may have an inline attribute that can be either "true" or "false".
|
|||
|
If the inline attribute is "true" the menu that is referenced may be copied into the
|
|||
|
current menu at the current point instead of being inserted as sub-menu of the current menu.
|
|||
|
The optional inline_limit attribute defines the maximum number of entries that can be inlined.
|
|||
|
If the sub-menu has more entries than inline_limit, the sub-menu will not be inlined.
|
|||
|
If the inline_limit is 0 (zero) there is no limit.
|
|||
|
The optional inline_title attribute defines whether an inlined menu should be preceeded with
|
|||
|
a header entry listing the caption of the sub-menu.
|
|||
|
The inline_title attribute can be either "true" or "false".
|
|||
|
The optional inline_alias attribute defines whether a single inlined entry should adopt the
|
|||
|
caption of the inlined menu. In such case no additional header entry will be added regardless
|
|||
|
of the value of the inline_title attribute.
|
|||
|
The inline_alias attribute can be either "true" or "false".
|
|||
|
Example: if a menu has a sub-menu titled "WordProcessor" with a single entry "OpenOffice 4.2",
|
|||
|
and both inline="true" and inline_alias="true" are specified then this would result in the
|
|||
|
"OpenOffice 4.2" entry being inlined in the current menu but the "OpenOffice 4.2" caption
|
|||
|
of the entry would be replaced with "WordProcessor".
|
|||
|
</p></dd><dt><span class="term"><Separator></span></dt><dd><p>
|
|||
|
This element may only appear as a child of a <Layout> or <DefaultLayout>
|
|||
|
menu. It indicates a suggestion to draw a visual separator at this point in the menu.
|
|||
|
<Separator> elements at the start of a menu, at the end of a menu or that directly
|
|||
|
follow other <Separator> elements may be ignored.
|
|||
|
</p></dd><dt><span class="term"><Merge type="menus"|"files"|"all"/></span></dt><dd><p>
|
|||
|
This element may only appear as a child of a <Layout> or <DefaultLayout>
|
|||
|
menu. It indicates the point where desktop entries and sub-menus that are not explicitly
|
|||
|
mentioned within the <Layout> or <DefaultLayout> element are to be inserted.
|
|||
|
It has a type attribute that indicates which elements should be inserted:
|
|||
|
type="menus"
|
|||
|
means that all sub-menus that are not explicitly mentioned should be inserted in
|
|||
|
alphabetical order of their visual caption at this point.
|
|||
|
type="files"
|
|||
|
means that all desktop entries
|
|||
|
contained in this menu that are not explicitly mentioned should be inserted in
|
|||
|
alphabetical order of their visual caption at this point.
|
|||
|
type="all" means that a mix of all sub-menus
|
|||
|
and all desktop entries that are not explicitly mentioned should be inserted in
|
|||
|
alphabetical order of their visual caption at this point.
|
|||
|
Each <Layout> or <DefaultLayout> element shall have exactly one <Merge type="all">
|
|||
|
element or it shall have exactly one <Merge type="files"> and exactly one
|
|||
|
<Merge type="menus"> element. An excemption is made for a completely empty <Layout>
|
|||
|
element which may be used to indicate that the default-layout should be used instead.
|
|||
|
</p></dd></dl></div><p>
|
|||
|
</p></div></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="merge-algorithm"></a>Merging</h2></div></div><div></div></div><p>
|
|||
|
Sometimes two menu layouts need to be merged. This is done when folding in
|
|||
|
legacy menu hierarchies (see <a href="#legacy-hierarchies" title="Legacy Menu Hierarchies">the section called “Legacy Menu Hierarchies”</a>) 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.
|
|||
|
</p><p>
|
|||
|
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."
|
|||
|
</p><p>
|
|||
|
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
|
|||
|
<a href="#legacy-hierarchies" title="Legacy Menu Hierarchies">the section called “Legacy Menu Hierarchies”</a>.
|
|||
|
</p><p>
|
|||
|
Continue processing until no <MergeFile>, <MergeDir>, or
|
|||
|
<LegacyDir> elements remain, taking care to avoid infinite loops
|
|||
|
caused by files that reference one another.
|
|||
|
</p><p>
|
|||
|
Once all files have been loaded into a single tree, scan the tree
|
|||
|
recursively performing these steps to remove duplicates:
|
|||
|
</p><div class="orderedlist"><ol type="1"><li><p>
|
|||
|
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 <span class="emphasis"><em>last</em></span> menu with that name.
|
|||
|
Delete all the newly empty <Menu> elements, keeping the
|
|||
|
last one.
|
|||
|
</p></li><li><p>
|
|||
|
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.
|
|||
|
</p></li><li><p>
|
|||
|
Resolve duplicate <Move> operations (with the same
|
|||
|
origin path) by keeping the last one.
|
|||
|
</p></li><li><p>
|
|||
|
Recurse into each child <Menu>, performing this list of
|
|||
|
steps for each child in order.
|
|||
|
</p></li></ol></div><p>
|
|||
|
</p><p>
|
|||
|
After recursing once to remove duplicates, resolve <Move> elements
|
|||
|
for each menu starting with the top level and recursing into child menus.
|
|||
|
So the deepest menus have their <Move> operations performed last.
|
|||
|
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.
|
|||
|
</p><p>
|
|||
|
If any <Move> operations affect a menu, then re-run the
|
|||
|
steps to resolve duplicates in case any duplicates have been
|
|||
|
created.
|
|||
|
</p><p>
|
|||
|
Finally, for each <Menu> containing a <Deleted> element which
|
|||
|
is not followed by a <NotDeleted> element, remove that menu and all
|
|||
|
its child menus.
|
|||
|
</p><p>
|
|||
|
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.
|
|||
|
</p><p>
|
|||
|
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.
|
|||
|
</p><p>
|
|||
|
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
|
|||
|
<tt class="filename"><i class="replaceable"><tt>datadir</tt></i>/applications/</tt> or it could
|
|||
|
install desktop files in a <tt class="filename"><i class="replaceable"><tt>datadir</tt></i>/applications/gnome</tt>
|
|||
|
subdirectory. When including legacy menu hierarchies the <tt class="literal">prefix</tt> argument
|
|||
|
of the <LegacyDir> element can be used to specify a prefix.
|
|||
|
</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="query-algorithm"></a>Generating the menus</h2></div></div><div></div></div><p>
|
|||
|
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.
|
|||
|
</p><p>
|
|||
|
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.
|
|||
|
</p><p>
|
|||
|
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. For each <Exclude>, match
|
|||
|
the rules against the currently-included desktop entries. For each
|
|||
|
desktop entry that matches, remove it again from the menu.
|
|||
|
</p><p>
|
|||
|
Two passes are necessary, once for regular menus, and
|
|||
|
once for <OnlyUnallocated> menus.
|
|||
|
</p><p>
|
|||
|
The result is a tree of desktop entries, of course.
|
|||
|
</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="legacy-hierarchies"></a>Legacy Menu Hierarchies</h2></div></div><div></div></div><p>
|
|||
|
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.
|
|||
|
</p><p>
|
|||
|
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>.
|
|||
|
</p><p>
|
|||
|
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>.
|
|||
|
</p><p>
|
|||
|
The menu layout corresponds conceptually to the following, though actually
|
|||
|
generating the XML is not necessary:
|
|||
|
</p><div class="itemizedlist"><ul type="disc"><li><p>
|
|||
|
For each directory in the legacy hierarchy, a
|
|||
|
<Menu> is created with the same <Name>
|
|||
|
as the directory on disk.
|
|||
|
</p></li><li><p>
|
|||
|
This menu then contains an <Include> element that includes
|
|||
|
each desktop entry in the directory. That is, it should have a
|
|||
|
|
|||
|
<Filename><i class="replaceable"><tt>Foo/Bar/foo.desktop</tt></i></Filename>
|
|||
|
for each desktop entry in the directory.
|
|||
|
</p><p>
|
|||
|
As a special exception, if a desktop entry in a directory contains
|
|||
|
a <tt class="varname">Categories</tt> field, that desktop entry should
|
|||
|
<span class="emphasis"><em>not</em></span> 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.
|
|||
|
</p></li><li><p>
|
|||
|
If the legacy directory contains a ".directory" file, then
|
|||
|
a <Directory> element should be generated that points to said
|
|||
|
".directory" file.
|
|||
|
</p></li><li><p>
|
|||
|
Legacy desktop entries should not be assigned any
|
|||
|
<tt class="varname">Categories</tt> 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>.)
|
|||
|
</p></li></ul></div><p>
|
|||
|
</p><p>
|
|||
|
For example, say we have the following legacy directory hierarchy:
|
|||
|
</p><div class="informalexample"><pre class="programlisting">
|
|||
|
/usr/share/applnk
|
|||
|
/usr/share/applnk/.directory
|
|||
|
/usr/share/applnk/bar.desktop
|
|||
|
/usr/share/applnk/System
|
|||
|
/usr/share/applnk/System/.directory
|
|||
|
/usr/share/applnk/System/foo.desktop
|
|||
|
</pre></div><p>
|
|||
|
Conceptually that is converted to the following <Menu>:
|
|||
|
</p><div class="informalexample"><pre class="programlisting">
|
|||
|
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 0.8//EN"
|
|||
|
"http://www.freedesktop.org/standards/menu-spec/menu-0.8.dtd">
|
|||
|
|
|||
|
<Menu>
|
|||
|
<Name>Applications</Name>
|
|||
|
<AppDir>/usr/share/applnk</AppDir>
|
|||
|
<DirectoryDir>/usr/share/applnk</DirectoryDir>
|
|||
|
<Directory>.directory</Directory>
|
|||
|
<Include>
|
|||
|
<Filename>bar.desktop</Filename>
|
|||
|
</Include>
|
|||
|
<Menu>
|
|||
|
<Name>System</Name>
|
|||
|
<AppDir>/usr/share/applnk/System</AppDir>
|
|||
|
<DirectoryDir>/usr/share/applnk/System</DirectoryDir>
|
|||
|
<Directory>.directory</Directory>
|
|||
|
<Include>
|
|||
|
<Filename>foo.desktop</Filename>
|
|||
|
</Include>
|
|||
|
</Menu>
|
|||
|
</Menu>
|
|||
|
</pre></div><p>
|
|||
|
This <Menu> is then merged as if it were in a file
|
|||
|
and loaded with <MergeFile>.
|
|||
|
</p></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="example"></a>Example Menu File</h2></div></div><div></div></div><p>
|
|||
|
</p><div class="informalexample"><pre class="programlisting">
|
|||
|
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 0.8//EN"
|
|||
|
"http://www.freedesktop.org/standards/menu-spec/menu-0.8.dtd">
|
|||
|
|
|||
|
<Menu>
|
|||
|
<Name>Applications</Name>
|
|||
|
<Directory>Applications.directory</Directory>
|
|||
|
|
|||
|
<-- Search the default locations -->
|
|||
|
<DefaultAppDirs/>
|
|||
|
<DefaultDirectoryDirs/>
|
|||
|
|
|||
|
<-- Merge third-party submenus -->
|
|||
|
<MergeDir>applications-merged</MergeDir>
|
|||
|
|
|||
|
<-- Merge legacy hierarchy -->
|
|||
|
<LegacyDir>/usr/share/applnk</LegacyDir>
|
|||
|
|
|||
|
<-- Define default layout -->
|
|||
|
<DefaultLayout>
|
|||
|
<Merge type="menus"/>
|
|||
|
<Merge type="files"/>
|
|||
|
<Separator/>
|
|||
|
<Menuname>More</Menuname>
|
|||
|
</DefaultLayout>
|
|||
|
|
|||
|
<-- some random moves, maybe to clean up legacy dirs,
|
|||
|
maybe from menu editing -->
|
|||
|
<Move>
|
|||
|
<Old>Foo</Old>
|
|||
|
<New>Bar</New>
|
|||
|
<Old>Foo2</Old>
|
|||
|
<New>Bar2</New>
|
|||
|
</Move>
|
|||
|
|
|||
|
<-- A preferences submenu, kept in a separate file
|
|||
|
so it can also be used standalone -->
|
|||
|
<Menu>
|
|||
|
<Name>Preferences</Name>
|
|||
|
<Directory>Preferences.directory</Directory>
|
|||
|
<MergeFile>preferences.menu</MergeFile>
|
|||
|
</Menu>
|
|||
|
|
|||
|
<-- An Office submenu, specified inline -->
|
|||
|
<Menu>
|
|||
|
<Name>Office</Name>
|
|||
|
<Directory>Office.directory</Directory>
|
|||
|
<Include>
|
|||
|
<Category>Office</Category>
|
|||
|
</Include>
|
|||
|
<Exclude>
|
|||
|
<Filename>foo.desktop</Filename>
|
|||
|
</Exclude>
|
|||
|
</Menu>
|
|||
|
|
|||
|
</Menu>
|
|||
|
</pre></div><p>
|
|||
|
</p></div><div class="appendix" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title"><a id="category-registry"></a>A. Registered Categories</h2></div></div><div></div></div><p>
|
|||
|
Remember, these are case-sensitive.
|
|||
|
When using a category described in the list below it is strongly
|
|||
|
recommended to also include the category listed under Related
|
|||
|
Categories. If a category has multiple related categories the most
|
|||
|
suitable related category should be included.
|
|||
|
</p><div class="informaltable"><table border="1"><colgroup><col /><col /></colgroup><thead><tr><th>Category</th><th>Description</th><th>Related Categories</th></tr></thead><tbody><tr><td>Legacy</td><td>Keyword that must be added to menu
|
|||
|
entries merged from legacy locations. May not actually exist in a
|
|||
|
desktop entry (should be stripped out if found there). 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></td></tr><tr><td>Core</td><td>Important application, core to the desktop such as a filemanager or a help browser</td><td> </td></tr><tr><td>Development</td><td>An application for development</td><td> </td></tr><tr><td>Building</td><td>A tool to build applications</td><td>Development</td></tr><tr><td>Debugger</td><td>A tool to debug applications</td><td>Development</td></tr><tr><td>IDE</td><td>IDE application</td><td>Development</td></tr><tr><td>GUIDesigner</td><td>A GUI designer application</td><td>Development</td></tr><tr><td>Profiling</td><td>A profiling tool</td><td>Development</td></tr><tr><td>RevisionControl</td><td>Applications like cvs or subversion</td><td>Development</td></tr><tr><td>Translation</td><td>A translation tool</td><td>Development</td></tr><tr><td>Office</td><td>An office type application</td><td class="auto-generated"> </td></tr><tr><td>Calendar</td><td>Calendar application</td><td>Office</td></tr><tr><td>ContactManagement</td><td>E.g. an addressbook</td><td>Office</td></tr><tr><td>Database</td><td>Application to manage a database</td><td>Office or Development or AudioVideo</td></tr><tr><td>Dictionary</td><td>A dictionary</td><td>Office</td></tr><tr><td>Chart</td><td>Chart application</td><td>Office</td></tr><tr><td>Email</td><td>Email application</td><td>Office;Network</td></tr><tr><td>Finance</td><td>Application to manage your finance</td><td>Office</td></tr><tr><td>FlowChart</td><td>A flowchart application</td><td>Office</td></tr><tr><td>PDA</td><td>Tool to manage your PDA</td><td>Office</td></tr><tr><td>ProjectManagement</td><td>Project management application</td><td>Office;Development</td></tr><tr><td>Presentation</td><td>Presentation software</td><td>Office</td></tr><tr><td>Spreadsheet</td><td>A spreadsheet</td><td>Office</td></tr><tr><td>WordProcessor</td><td>A word processor</td><td>Office</td></tr><tr><td>Graphics</td><td>Graphical application</td><td class="auto-generated"> </td></tr><tr><td>2DGraphics</td><td>2D based graphical application</td><td>Graphics</td></tr><tr><td>VectorGraphics</td><td>Vector based graphical application</td><td>2DGraphics</td></tr><tr><td>RasterGraphics</td><td>Raster based graphical application</td><td>2DGraphics</td></tr><tr><td>3DGraphics</td><td>3D based graphical application</td><td>Graphics</td></tr><tr><td>Scanning</td><td>Tool to scan a file/text</td><td>Graphics</td></tr><tr><td>OCR</td><td>Tool to text</td><td>Scanning</td></tr><tr><td>Photograph</td><td>Camera tools, etc.</td><td>Graphics or Office</td></tr><tr><td>Viewer</td><td>Tool to view e.g. a graphic or pdf file</td><td>Graphics or Office</td></tr><tr><td>Settings</td><td>Settings applications</td><td class="auto-generated"> </td></tr><tr><td>DesktopSettings</td><td>ConfigurationTool for the GUI</td><td>Settings</td></tr><tr><td>HardwareSettings</td><td>A tool to manage hardware components, like soundcards, graphicards or printers</td><td>Settings</td></tr><tr><td>PackageManager</td><td>A package manager application</td><td>Settings</td></tr><tr><td>Network</td><td>Network application such as a webbrowser</td><td>(Settings)</td></tr><tr><td>Dialup</td><td>A dialup program</td><td>Network</td></tr><tr><td>InstantMessaging</td><td>An InstantMessaging Client</td><td>Network</td></tr><tr><td>IRCClient</td><td>An IRC Client</td><td>Network</td></tr><tr><td>FileTransfer</td><td>Tools like FTP or P2P programs</td><td>Network</td></tr><tr><td>HamRadio</td><td>HAM radio software</td><td>Network or Audio</td></tr><tr><td>News</td><td>A newsreader or newsticker</td><td class="auto-generated"> </td></tr><tr><td>P2P</td><td>A P2P program</td><td>Network</td></tr><tr><td>RemoteAccess</td><td>A tool to remotely manage your PC</td><td>Network</td></tr><tr><td>Telephony</td><td>Telephony via PC</td><td>Network</td></tr><tr><td>WebBrowser</td><td>A webbrowser</td><td>Network</td></tr><tr><td>WebDevelopment</td><td>A tool for web developers</td><td>Network or Development</td></tr><tr><td>AudioVideo</td><td>A multimedia (audio/video) application</td><td class="auto-generated"> <
|
|||
|
<tt class="filename">bash</tt> or <tt class="filename">tcsh</tt>, not a TerminalEmulator)</td><td class="auto-generated"> </td></tr><tr><td>Screensaver</td><td>A screensaver (launching this desktop entry should activate the screensaver)</td><td> </td></tr><tr><td>TerminalEmulator</td><td>A terminal emulator application</td><td> </td></tr><tr><td>TrayIcon</td><td>An application that is primarily an icon for the "system tray" or "notification area" (apps that open a normal window and just happen to have a tray icon as well should not list this category)</td><td> </td></tr><tr><td>System</td><td>System application, "System Tools" such as say a log viewer or network monitor</td><td>(Settings)</td></tr><tr><td>Filesystem</td><td>A filesytem tool</td><td>System</td></tr><tr><td>Monitor</td><td>Monitor application/applet that monitors some resource or activity</td><td>System</td></tr><tr><td>Security</td><td>A security tool</td><td>Settings or System</td></tr><tr><td>Utility</td><td>Small utility application, "Accessories"</td><td> </td></tr><tr><td>Accessibility</td><td>Accessibility</td><td>Settings or Utility</td></tr><tr><td>Calculator</td><td>A calculator</td><td>Utilitiy</td></tr><tr><td>Clock</td><td>A clock application/applet</td><td>Utility</td></tr><tr><td>TextEditor</td><td>A text editor</td><td>Utilitiy</td></tr><tr><td>KDE</td><td>Application based on KDE libraries</td><td>QT</td></tr><tr><td>GNOME</td><td>Application based on GNOME libraries</td><td>GTK</td></tr><tr><td>GTK</td><td>Application based on GTK+ libraries</td><td> </td></tr><tr><td>Qt</td><td>Application based on Qt libraries</td><td> </td></tr><tr><td>Motif</td><td>Application based on Motif libraries</td><td> </td></tr><tr><td>Java</td><td>Application based on Java awt or Swing</td><td> </td></tr><tr><td>ConsoleOnly</td><td>Application that only works inside a terminal (text-based or command line application)</td><td> </td></tr></tbody></table></div><p>
|
|||
|
|
|||
|
</p></div><div class="appendix" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title"><a id="onlyshowin-registry"></a>B. Registered OnlyShowIn Environments</h2></div></div><div></div></div><p>
|
|||
|
Remember, these are case-sensitive. "KDE" not "kde" should be
|
|||
|
used.
|
|||
|
</p><div class="informaltable"><table border="1"><colgroup><col /><col /></colgroup><thead><tr><th>OnlyShowIn Value</th><th>Environment</th></tr></thead><tbody><tr><td>GNOME</td><td>GNOME Desktop</td></tr><tr><td>KDE</td><td>KDE Desktop</td></tr><tr><td>ROX</td><td>ROX Desktop</td></tr><tr><td>XFCE</td><td>XFCE Desktop</td></tr><tr><td>Old</td><td>Legacy menu systems</td></tr></tbody></table></div><p>
|
|||
|
</p></div><div class="appendix" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title"><a id="third-party-howto"></a>C. How to add your application to the menus</h2></div></div><div></div></div><p>
|
|||
|
The short answer for third party applications is:
|
|||
|
</p><div class="itemizedlist"><ul type="disc"><li><p>
|
|||
|
Install desktop entries to
|
|||
|
<i class="replaceable"><tt>datadir</tt></i>/applications/ for each menu
|
|||
|
item. Please namespace the filename, as in "vendor-foo.desktop", or
|
|||
|
use a subdirectory of
|
|||
|
<i class="replaceable"><tt>datadir</tt></i>/applications/ so you have
|
|||
|
"vendor/foo.desktop." Please be sure all desktop entries are valid
|
|||
|
(see the <a href="http://www.freedesktop.org/software/desktop-file-utils/" target="_top">
|
|||
|
desktop-file-utils</a> package for a validation utility).
|
|||
|
</p></li><li><p>
|
|||
|
Install an XML menu file to <i class="replaceable"><tt>sysconfdir</tt></i>/desktop/menus/applications-merged/ to add any submenus, if your desktop entries aren't already
|
|||
|
included in some common categories.
|
|||
|
</p></li><li><p>
|
|||
|
Install any directory entries needed for your submenus to <i class="replaceable"><tt>datadir</tt></i>/desktop-directories/, taking care to namespace and validate
|
|||
|
the directory entries.
|
|||
|
</p></li></ul></div><p>
|
|||
|
</p><p>
|
|||
|
Also, at least for a good long while, installing a directory hierarchy to
|
|||
|
the old GNOME/KDE specific locations such as /usr/share/applnk and
|
|||
|
/usr/share/gnome/apps should work. There are two ways to support
|
|||
|
both the old and new menu systems at the same time:
|
|||
|
</p><div class="itemizedlist"><ul type="disc"><li><p>
|
|||
|
If you add a <tt class="varname">Categories</tt> 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 <tt class="varname">Categories</tt> 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.
|
|||
|
</p></li><li><p>
|
|||
|
If you add the line <tt class="literal">OnlyShowIn=Old;</tt> to a desktop
|
|||
|
entry, then old legacy implementations that ignore
|
|||
|
<tt class="varname">OnlyShowIn</tt> will still show the desktop entry, but
|
|||
|
implementations of this specification will not. Thus you can
|
|||
|
add an "<tt class="literal">OnlyShowIn=Old;</tt>" entry to the legacy
|
|||
|
hierarchy, and a new-style desktop entry to
|
|||
|
<i class="replaceable"><tt>datadir</tt></i>/applications/, and still get
|
|||
|
only one entry in the menus.
|
|||
|
</p></li></ul></div><p>
|
|||
|
</p></div><div class="appendix" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title"><a id="implementation-notes"></a>D. Implementation notes</h2></div></div><div></div></div><div class="sect1" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a id="menu-editing"></a>Menu editing</h2></div></div><div></div></div><p>
|
|||
|
To implement menu editing, the intent is that a per-user file is
|
|||
|
created. The per-user file should specify a <MergeFile> with the
|
|||
|
systemwide file, so that system changes are inherited. When the user
|
|||
|
deletes a menu item, you add
|
|||
|
<tt class="literal"><Exclude><Filename>foo.desktop</Filename></Exclude></tt>. If
|
|||
|
the user adds a menu item, you use
|
|||
|
<tt class="literal"><Include><Filename>foo.desktop</Filename></Include></tt>.
|
|||
|
</p><p>
|
|||
|
If the user moves a folder, you might try to use <Move> elements
|
|||
|
to represent that, but it's tricky. (Move A/B/C to D/E/F, then move D/E
|
|||
|
to D/G, note that D/E/F still contains A/B/C while only the original D/E
|
|||
|
was moved to D/G.) In order to move a folder, you have to "fix up"
|
|||
|
all moves that move things <span class="emphasis"><em>into</em></span> the folder being
|
|||
|
moved to instead move things into the folder's new location.
|
|||
|
</p><p>
|
|||
|
To delete a folder, simply append the <Deleted> element.
|
|||
|
</p><p>
|
|||
|
Menu editors probably need to do some kind of consolidation/compression
|
|||
|
to avoid an XML tree that grows infinitely over time.
|
|||
|
</p></div></div><div class="glossary"><div class="titlepage"><div><div><h2 class="title"><a id="id2506596"></a>Glossary</h2></div></div><div></div></div><p>
|
|||
|
This glossary defines some of the terms used in this specification.
|
|||
|
</p><dl><dt><a id="term-desktop-entry"></a>Desktop entry</dt><dd><p>
|
|||
|
A desktop entry is a file with a name ending in the ".desktop"
|
|||
|
extension which conforms to the <a href="http://www.freedesktop.org/standards/desktop-entry-spec" target="_top">desktop
|
|||
|
entry specification</a>. 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."
|
|||
|
</p></dd><dt><a id="term-desktop-file-id"></a>Desktop-File Id</dt><dd><p>
|
|||
|
The id to identify a desktop entry with.
|
|||
|
For example, if <tt class="filename">/usr/share/applications</tt> is
|
|||
|
specified as an <AppDir>, and <tt class="filename">/opt/fop</tt>
|
|||
|
as a <LegacyDir> with a prefix of <tt class="literal">foo-</tt>
|
|||
|
then
|
|||
|
<tt class="filename">/usr/share/applications/foo/bar.desktop</tt>,
|
|||
|
<tt class="filename">/usr/share/applications/foo-bar.desktop</tt>
|
|||
|
and
|
|||
|
<tt class="filename">/opt/fop/Settings/bar.desktop</tt> all have
|
|||
|
the same desktop-file id <tt class="literal">foo-bar.desktop</tt>
|
|||
|
</p></dd><dt><a id="term-directory-entry"></a>Directory entry</dt><dd><p>
|
|||
|
A directory entry is a file with a name ending in the ".directory"
|
|||
|
extension which conforms to the <a href="http://www.freedesktop.org/standards/desktop-entry-spec" target="_top">desktop
|
|||
|
entry specification</a>. It describes gives a localized name and
|
|||
|
an icon for a submenu.
|
|||
|
Directory entries are also known as ".directory files."
|
|||
|
</p></dd><dt><a id="term-menu-path"></a>Menu path</dt><dd><p>
|
|||
|
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.
|
|||
|
</p></dd><dt><a id="term-relative-path"></a>Relative path</dt><dd><p>
|
|||
|
The canonical path to a directory entry, relative to the
|
|||
|
<DirectoryDir> containing the
|
|||
|
entry. For example, if <tt class="filename">/usr/share/desktop-directories</tt> is
|
|||
|
specified as an <DirectoryDir>, the relative path to
|
|||
|
<tt class="filename">/usr/share/desktop-directories/foo/bar.directory</tt> is
|
|||
|
<tt class="filename">foo/bar.directory</tt>.
|
|||
|
</p></dd></dl></div></div></body></html>
|