diff options
| -rw-r--r-- | basedir/basedir-spec.xml | 215 | ||||
| -rw-r--r-- | menu/menu-spec.xml | 1507 | ||||
| -rw-r--r-- | systemtray/systemtray-spec.xml | 342 | 
3 files changed, 2064 insertions, 0 deletions
| diff --git a/basedir/basedir-spec.xml b/basedir/basedir-spec.xml new file mode 100644 index 0000000..feb57c0 --- /dev/null +++ b/basedir/basedir-spec.xml @@ -0,0 +1,215 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +                  "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +				  ]> +<article id="index"> +  <artheader> +    <title>XDG Base Directory Specification</title> +    <releaseinfo>Version 0.5</releaseinfo> +    <date>9 June 2003</date> +    <authorgroup> +      <author> +	<firstname>Waldo</firstname> +	<surname>Bastian</surname> +	<affiliation> +	  <address> +	    <email>bastian@kde.org</email> +	  </address> +	</affiliation> +      </author> +    </authorgroup> +  </artheader> + +  <sect1 id="introduction"> +    <title>Introduction</title> +    <para> +      Various specifications specify files and file formats. This  +      specification defines where these files should be looked for by  +      defining one or more base directories relative to which files  +      should be located.  +    </para> +  </sect1> + +  <sect1 id="basics"> +    <title>Basics</title> +    <para> +      The XDG Base Directory Specification is based on four concepts:  +      <itemizedlist> +        <listitem> +          <para> +            There is a single base directory relative to which user-specific +            data files should be written. This directory is defined by the +            environment variable <literal>$XDG_DATA_HOME</literal>. +          </para> +        </listitem> +        <listitem> +          <para> +            There is a single base directory relative to which user-specific +            configuration files should be written. This directory is defined by the +            environment variable <literal>$XDG_CONFIG_HOME</literal>. +          </para> +        </listitem> +        <listitem> +          <para> +            There is a set of preference ordered base directories relative to +            which data files should be searched.  This set of directories is defined +            by the environment variable <literal>$XDG_DATA_DIRS</literal>. +          </para> +        </listitem> +        <listitem> +          <para> +            There is a set of preference ordered base directories relative to +            which configuration files should be searched.   +            This set of directories is defined +            by the environment variable <literal>$XDG_CONFIG_DIRS</literal>. +          </para> +        </listitem> +      </itemizedlist> +    </para> +  </sect1> + + +  <sect1 id="variables"> +    <title>Environment variables</title> +    <para> +      <literal>$XDG_DATA_HOME</literal> defines the base directory relative to +      which user specific data files should be stored. If +      <literal>$XDG_DATA_HOME</literal> is either not set or empty, a default equal to +      <literal>$HOME</literal>/.local/share should be used. +    </para> +    <para> +      <literal>$XDG_CONFIG_HOME</literal> defines the base directory relative to +      which user specific configuration files should be stored. If +      <literal>$XDG_CONFIG_HOME</literal> is either not set or empty, a default equal to +      <literal>$HOME</literal>/.config should be used. +    </para> +    <para> +      <literal>$XDG_DATA_DIRS</literal> defines the preference-ordered set of +      base directories to search for data files in addition to the  +      <literal>$XDG_DATA_HOME</literal> base directory. +      The directories in <literal>$XDG_DATA_DIRS</literal> should be seperated  +      with a colon ':'. +    </para> +    <para> +      If <literal>$XDG_DATA_DIRS</literal> is either not set or empty, a value equal to +      /usr/local/share/:/usr/share/ should be used.  +    </para> +    <para> +      <literal>$XDG_CONFIG_DIRS</literal> defines the preference-ordered set of +      base directories to search for configuration files in addition to the  +      <literal>$XDG_CONFIG_HOME</literal> base directory. +      The directories in <literal>$XDG_CONFIG_DIRS</literal> should be seperated  +      with a colon ':'. +    </para> +    <para> +      If <literal>$XDG_CONFIG_DIRS</literal> is either not set or empty, a value equal to +      /etc/xdg should be used.  +    </para> +    <para> +      The order of base directories denotes their importance; the first +      directory listed is the most important. When the same information is +      defined in multiple places the information defined relative to the more +      important base directory takes precedent. The base directory defined +      by <literal>$XDG_DATA_HOME</literal> is considered more important than  +      any of the base directories defined by <literal>$XDG_DATA_DIRS</literal>. +      The base directory defined +      by <literal>$XDG_CONFIG_HOME</literal> is considered more important than +      any of the base directories defined by <literal>$XDG_CONFIG_DIRS</literal>. +    </para> +    <para> +       +    </para> +  </sect1> + +  <sect1 id="referencing"> +    <title>Referencing this specification</title> +    <para> +      Other specifications may reference this specification by specifying the +      location of a data file as +      <literal>$XDG_DATA_DIRS</literal>/subdir/filename. This implies that: +      <itemizedlist> +        <listitem> +          <para> +            Such file should be installed to <literal>$datadir</literal>/subdir/filename +            with <literal>$datadir</literal> defaulting to /usr/share. +          </para> +        </listitem> +        <listitem> +          <para> +            A user specific version of the data file may be created in +            <literal>$XDG_DATA_HOME</literal>/subdir/filename, taking into +            account the default value for <literal>$XDG_DATA_HOME</literal> if +            <literal>$XDG_DATA_HOME</literal> is not set. +          </para> +        </listitem> +        <listitem> +          <para> +            Lookups of the data file should search for ./subdir/filename relative to +            all base directories specified by <literal>$XDG_DATA_HOME</literal> and  +            <literal>$XDG_DATA_DIRS</literal> . If an environment  +            variable is either not set or empty, its default value as defined by this specification  +            should be used instead. +          </para> +        </listitem> +      </itemizedlist> +    </para> +    <para> +      Specifications may reference this specification by specifying the +      location of a configuration file as +      <literal>$XDG_CONFIG_DIRS</literal>/subdir/filename. This implies that: +      <itemizedlist> +        <listitem> +          <para> +            Default configuration files should be installed to <literal>$sysconfdir</literal>/xdg/subdir/filename +            with <literal>$sysconfdir</literal> defaulting to /etc. +          </para> +        </listitem> +        <listitem> +          <para> +            A user specific version of the configuration file may be created in +            <literal>$XDG_CONFIG_HOME</literal>/subdir/filename, taking into +            account the default value for <literal>$XDG_CONFIG_HOME</literal> if +            <literal>$XDG_CONFIG_HOME</literal> is not set. +          </para> +        </listitem> +        <listitem> +          <para> +            Lookups of the configuration file should search for ./subdir/filename relative to +            all base directories indicated by <literal>$XDG_CONFIG_HOME</literal> and  +            <literal>$XDG_CONFIG_DIRS</literal> . If an environment  +            variable is either not set or empty, its default value as defined by this specification  +            should be used instead. +          </para> +        </listitem> +      </itemizedlist> +    </para> +    <para> +      If, when attempting to write a file, the destination  +      directory is non-existant an attempt should be made to create it  +      with permission <literal>0700</literal>. If the destination directory +      exists already the permissions should not be changed. +      The application should be prepared to handle the case where the file  +      could not be written, either because the directory was non-existant  +      and could not be created, or for any other reason. In such case it  +      may chose to present an error message to the user. +    </para> +    <para> +      When attempting to read a file, if for any reason a file in a certain +      directory is unaccessible, e.g. because the directory is non-existant,  +      the file is non-existant or the user is not authorized to open the file, +      then the processing of the file in that directory should be skipped.  +      If due to this a required file could not be found at all, the  +      application may chose to present an error message to the user. +    </para> +    <para> +      A specification that refers to <literal>$XDG_DATA_DIRS</literal> or  +      <literal>$XDG_CONFIG_DIRS</literal> should define what the behaviour  +      must be when a file is located under multiple base directories.  +      It could, for example, define that only the file under the most  +      important base directory should be used or, as another example, +      it could define rules for merging the information from the different +      files. +    </para> +  </sect1> + +</article> + diff --git a/menu/menu-spec.xml b/menu/menu-spec.xml new file mode 100644 index 0000000..d48e2aa --- /dev/null +++ b/menu/menu-spec.xml @@ -0,0 +1,1507 @@ +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +                  "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +				  ]> +<article id="index"> +  <artheader> +    <title>Desktop Menu Specification</title> +    <releaseinfo>Version 0.4</releaseinfo> +    <date>31 May 2003</date> +    <authorgroup> +      <author> +	<firstname>Waldo</firstname> +	<surname>Bastian</surname> +	<affiliation> +	  <address> +	    <email>waldo@kde.org</email> +	  </address> +	</affiliation> +      </author> +      <author> +	<firstname>Francois</firstname> +	<surname>Gouget</surname> +	<affiliation> +	  <address> +	    <email>fgouget@codeweavers.com</email> +	  </address> +	</affiliation> +      </author> +      <author> +	<firstname>Alex</firstname> +	<surname>Graveley</surname> +	<affiliation> +	  <address> +	    <email>alex@ximian.com</email> +	  </address> +	</affiliation> +      </author> +      <author> +	<firstname>George</firstname> +	<surname>Lebl</surname> +	<affiliation> +	  <address> +	    <email>jirka@5z.com</email> +	  </address> +	</affiliation> +      </author> +      <author> +	<firstname>Havoc</firstname> +	<surname>Pennington</surname> +	<affiliation> +	  <address> +	    <email>hp@pobox.com</email> +	  </address> +	</affiliation> +      </author> +    </authorgroup> +  </artheader> + +  <sect1 id="introduction"> +    <title>Introduction</title> +    <para> +      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. +    </para> +    <para> +      The basic scheme is very simple. Information about each application (menu +      item) is stored in a desktop entry (see <ulink +        url="http://www.freedesktop.org/standards/desktop-entry-spec.html">Desktop +      Entry Standard</ulink>).  Then an XML configuration file defines the +      hierarchical arrangement (layout) of menu items, and which menu items are +      actually displayed. +    </para> +    <para> +      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 +      <firstterm>merging</firstterm> two menu layouts. +    </para> +  </sect1> +  <sect1 id="paths"> +    <title>File locations</title> +    <para> +      Files involved in this specification are located according to the "desktop +      base directory specification" which can be found on <ulink +      url="http://www.freedesktop.org/standards/">www.freedesktop.org</ulink>. +    </para> +    <para> +      Here are the files defined by this specification: +      <variablelist> +        <varlistentry> +          <term><varname>$XDG_CONFIG_DIRS</varname>/menus/applications.menu</term> +          <listitem> +            <para> +              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.) +            </para> +            <para> +              Other menu files may exist, but are not specified in this +              document. +            </para> +          </listitem> +        </varlistentry> +        <varlistentry> +          <term><varname>$XDG_CONFIG_DIRS</varname>/menus/<replaceable>menu-file-basename</replaceable>-merged/</term> +          <listitem> +            <para> +              One of the default merge directories included in the +              <DefaultMergeDirs> element.  By convention, third parties +              may add new <Menu> files in this +              location. <replaceable>menu-file-basename</replaceable> means the +              "applications" from "applications.menu" for example. So the merge +              directory would be "applications-merged". +            </para> +          </listitem> +        </varlistentry> +        <varlistentry> +          <term><varname>$XDG_DATA_DIRS</varname>/applications/</term> +          <listitem> +            <para> +              This directory contains a .desktop file for each possible menu +              item. Each directory in the <varname>$XDG_DATA_DIRS</varname> +              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. +            </para> +            <para> +              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. +            </para> +          </listitem> +        </varlistentry> +        <varlistentry> +          <term><varname>$XDG_DATA_DIRS</varname>/desktop-directories/</term> +          <listitem> +            <para> +              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. +            </para> +            <para> +              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. +            </para> +          </listitem> +        </varlistentry> +      </variablelist> +    </para> +  </sect1> +  <sect1 id="desktop-entry-extensions"> +    <title>Extensions to the desktop entry format</title> +    <para> +      This specification adds two new fields to <ulink +url="http://www.freedesktop.org/standards/desktop-entry-spec.html">desktop +entries</ulink>: <varname>Categories</varname> and +      <varname>OnlyShowIn</varname>. +    </para> +    <para> +      The <varname>Categories</varname> field is a list of strings used to +      classify menu items. For example, applications in the +      <literal>AudioVideo</literal> category might end up in the "Sound & +	  Video" submenu. <xref linkend="category-registry"/> 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. +    </para> +    <para> +      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. +    </para> +    <para> +      The <varname>OnlyShowIn</varname> field is a list of strings identifying +      the environments that should display a given menu item.  If an +      <varname>OnlyShowIn</varname> 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. <xref +	  linkend="onlyshowin-registry"/> enumerates the strings to use for +      some common environments. +    </para> +    <sect2 id="desktop-entry-extensions-examples"> +      <title>Examples of using <varname>Categories</varname> and <varname>OnlyShowIn</varname></title> +      <para> +        A desktop entry for a Qt-based image viewer might contain  +        this <varname>Categories</varname> line: +        <informalexample> +          <programlisting> +            Categories=Qt;Graphics;RasterGraphics;Viewer; +          </programlisting> +        </informalexample> +      </para> +      <para> +        A desktop entry for Octave, a command-line mathematics program (which +        would also have the field <literal>Terminal=true</literal>), might have: +        <informalexample> +          <programlisting> +            Categories=ConsoleOnly;Math; +          </programlisting> +        </informalexample> +      </para> +      <para> +        A desktop entry for a GNOME-specific calculator program +        that should only appear in GNOME might have: +        <informalexample> +          <programlisting> +            Categories=GNOME;Utility; +            OnlyShowIn=GNOME; +          </programlisting> +        </informalexample> +        Note that the <varname>OnlyShowIn</varname> field is a +        <emphasis>list</emphasis> and thus ends in a semicolon. +      </para> +    </sect2> +  </sect1> +  <sect1 id="menu-file-format"> +    <title>Format of menu files</title> +    <para> +      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. +    </para> +    <sect2 id="menu-file-doctype"> +      <title>Doctype Declaration</title> +      <para> +        Menu files for this version of the specification must use the following +        namespace, public and system identifiers: +        <variablelist> +          <varlistentry> +            <term>Namespace</term> +            <listitem> +              <para> +                <literal>http://www.freedesktop.org/standards/menu</literal> +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term>Public Identifier for 1.0</term> +            <listitem> +              <para> +                <literal>PUBLIC "-//freedesktop//DTD Menu 1.0//EN"</literal> +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term>System Identifier for 1.0</term> +            <listitem> +              <para> +                <literal>http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd</literal> +              </para> +            </listitem> +          </varlistentry> +        </variablelist> + +        Here is a sample doctype declaration: +        <informalexample> +          <programlisting> +            <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" +            "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> +          </programlisting> +        </informalexample> +         +        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). +      </para> +    </sect2> +    <sect2 id="menu-file-elements"> +      <title>Elements</title> +      <para> +        <variablelist> +          <varlistentry> +            <term><Menu></term> +            <listitem> +              <para> +                The root element is <Menu>.  Each <Menu> element may +                contain any number of nested <Menu> elements, indicating submenus. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><AppDir></term> +            <listitem> +              <para> +                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. +              </para> +              <para> +                Desktop entries in the pool of available entries are identified +                by their <firstterm>relative path</firstterm> (see <xref +				linkend="term-relative-path"/>). +              </para> +              <para> +                <AppDir> elements appearing later in the menu file have +                priority in case of collisions between relative paths. +              </para> +              <para> +                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. An <AppDir> should be recursively +                scanned, finding all desktop entries below the given directory. +                Only files ending in ".desktop" should be used, other files are +                ignored. +              </para> +              <para> +                Duplicate <AppDir> elements (that specify the same +                directory) should be ignored, but the <emphasis>last</emphasis> +                duplicate in the file should be used when establishing the order +                in which to scan the directories. This is important when merging +				(see <xref linkend="merge-algorithm"/>). The order of +                <AppDir> elements with respect to <Include> and +                <Exclude> elements is not relevant, also to facilitate +                merging. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><DefaultAppDirs></term> +            <listitem> +              <para> +                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 +                (<replaceable>datadir</replaceable>/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. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><DirectoryDir></term> +            <listitem> +              <para> +                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. +              </para> +              <para> +                  Directory entries in the pool of available entries are identified +                  by their <firstterm>relative path</firstterm> (see <xref +				  linkend="term-relative-path"/>). +              </para> +              <para> +                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. +              </para> +              <para> +                Duplicate <DirectoryDir> elements (that specify the same +                directory) are handled as with duplicate <AppDir> +                elements (the last duplicate is used). +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><DefaultDirectoryDirs></term> +            <listitem> +              <para> +                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 +                (<replaceable>datadir</replaceable>/desktop-directories/ etc.). The default +                locations that are earlier in the search path go later in the +                <Menu> so that they have priority. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Name></term> +            <listitem> +              <para> +                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 <xref linkend="term-menu-path"/>. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Directory></term> +            <listitem> +              <para> +                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. +              </para> +              <para> +                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. +              </para>               +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><OnlyUnallocated> and <NotOnlyUnallocated></term> +            <listitem> +              <para> +                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>. +              </para> +              <para> +                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 <xref linkend="query-algorithm"/>. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Deleted> and <NotDeleted></term> +            <listitem> +              <para> +                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. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Include></term> +            <listitem> +              <para> +                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. +              </para> +              <para> +                <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 <xref linkend="merge-algorithm"/>. +				See <xref linkend="query-algorithm"/> for full details on  +                    how to process <Include> and <Exclude> elements. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Exclude></term> +            <listitem> +              <para> +                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.) +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Filename></term> +            <listitem> +              <para> +                The <Filename> element is the most basic matching rule. +                It matches a desktop entry if the desktop entry has the given +                relative path. Absolute paths <emphasis>must not be used</emphasis>,  +                and relative paths must be the canonical form used to reference  +                a desktop entry in the pool of desktop entries (they can't  +                contain ".." or anything of that nature, and can't contain  +				extra "/" characters). See <xref linkend="term-relative-path"/>. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Category></term> +            <listitem> +              <para> +                The <Category> element is another basic matching +                predicate. It matches a desktop entry if the desktop entry has +                the given category in its <varname>Categories</varname> field. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><All></term> +            <listitem> +              <para> +                The <All> element is a matching rule that matches  +                all desktop entries. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><And></term> +            <listitem> +              <para> +                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. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Or></term> +            <listitem> +              <para> +                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. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Not></term> +            <listitem> +              <para> +                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 +                <emphasis>not</emphasis> match the desktop entry. That is, +                matching rules below <Not> have a logical OR relationship. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><MergeFile></term> +            <listitem> +              <para> +                  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. <xref linkend="merge-algorithm"/> +                  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. +              </para> +              <para> +                Duplicate <MergeFile> elements (that specify the same +                file) are handled as with duplicate <AppDir> +                elements (the last duplicate is used). +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><MergeDir></term> +            <listitem> +              <para> +                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. +              </para> +              <para> +                Duplicate <MergeDir> elements (that specify the same +                directory) are handled as with duplicate <AppDir> +                elements (the last duplicate is used). +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><DefaultMergeDirs></term> +            <listitem> +              <para> +                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. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><LegacyDir></term> +            <listitem> +              <para> +                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 <xref +				linkend="legacy-hierarchies"/> 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. +              </para> +              <para> +                Duplicate <LegacyDir> elements (that specify the same +                directory) are handled as with duplicate <AppDir> +                elements (the last duplicate is used). +              </para> +              <para> +                The <LegacyDir> element may have one attribute, +                <literal>prefix</literal>. Normally, given a <LegacyDir> +                <filename>/foo/bar</filename> and desktop entry +                <filename>/foo/bar/baz/Hello.desktop</filename> the desktop +                entry would be included as +                <filename>baz/Hello.desktop</filename>.  Given a prefix of +                <literal>boo-</literal>, it would instead be loaded as +                <filename>boo-Hello.desktop</filename>. In other words, if a +                prefix is present it replaces the relative path to the desktop +                or directory entry. The prefix may contain path separator ('/') +                characters. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><KDELegacyDirs></term> +            <listitem> +              <para> +                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. 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. +                [FIXME what are the exact <LegacyDir prefix="???"> that  +                this expands to?] +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Move></term> +            <listitem> +              <para> +                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 <xref +				linkend="merge-algorithm"/> for details). +              </para> +              <para> +                <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. +              </para> +              <para> +                <Move> may or may not be useful for implementing menu  +				editing, see <xref linkend="menu-editing"/>. +              </para> +              <para> +                Duplicate <Move> elements are merged as specified in <xref +				linkend="merge-algorithm"/>.  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. +              </para> +              <para> +                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". +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><Old></term> +            <listitem> +              <para> +                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  +				<xref linkend="term-menu-path"/>). +                Paths are interpreted relative to the menu containing  +                the <Move> element. +              </para> +            </listitem> +          </varlistentry> +          <varlistentry> +            <term><New></term> +            <listitem> +              <para> +                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. +              </para> +            </listitem> +          </varlistentry> +        </variablelist> +      </para> +    </sect2> +  </sect1> + +  <sect1 id="merge-algorithm"> +    <title>Merging</title> +    <para> +      Sometimes two menu layouts need to be merged. This is done when folding in +	  legacy menu hierarchies (see <xref linkend="legacy-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. +    </para> +    <para> +      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." +    </para> +    <para> +      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  +	  <xref linkend="legacy-hierarchies"/>. +    </para> +    <para> +      Continue processing until no <MergeFile>, <MergeDir>, or +      <LegacyDir> elements remain, taking care to avoid infinite loops +      caused by files that reference one another. +    </para> +    <para> +      Once all files have been loaded into a single tree, scan the tree  +      recursively performing these steps: +      <orderedlist> +        <listitem> +          <para> +            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 <emphasis>last</emphasis> menu with that name. +            Delete all the newly empty <Menu> elements, keeping the  +            last one. +          </para> +        </listitem> +        <listitem> +          <para> +            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. +          </para> +        </listitem> +        <listitem> +          <para> +            Recurse into each child <Menu>, performing this list of  +            steps for each child in order. +          </para> +        </listitem> +        <listitem> +          <para> +            Resolve duplicate <Move> operations (with the same  +            origin path) by keeping the last one. +          </para> +        </listitem> +        <listitem> +          <para> +            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. Then, recursively re-run +            the previous merge steps on the resulting combined <Menu> in order to +            consolidate duplicates. +          </para> +        </listitem> +        <listitem> +          <para> +            For each <Menu> containing a <Deleted> element which is +            not followed by a <NotDeleted> element, remove that menu. +          </para> +        </listitem> +      </orderedlist> +    </para> + +    <para> +      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. +    </para> +  </sect1> + +  <sect1 id="query-algorithm"> +    <title>Generating the menus</title> +    <para> +      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. +    </para> +    <para> +      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 relative path, 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 +      relative path), the entry for the child menu has priority. +    </para> +    <para> +      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. +    </para> +    <para> +      Two passes are necessary, once for regular menus, and  +      once for <OnlyUnallocated> menus. +    </para> +    <para> +      The result is a tree of desktop entries, of course. +    </para> +  </sect1> + +  <sect1 id="legacy-hierarchies"> +    <title>Legacy Menu Hierarchies</title> +    <para> +      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. +    </para> +    <para> +      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>. +    </para> +    <para> +      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>. +    </para> +    <para> +      The menu layout corresponds conceptually to the following, though actually +      generating the XML is not necessary: +      <itemizedlist> +        <listitem> +          <para> +            For each directory in the legacy hierarchy, a  +            <Menu> is created with the same <Name>  +            as the directory on disk. +          </para> +        </listitem> +        <listitem> +          <para> +            This menu then contains an <Include> element that includes +            each desktop entry in the directory.  That is, it should have a  +             +            <Filename><replaceable>Foo/Bar/foo.desktop</replaceable></Filename> +            for each desktop entry in the directory. +          </para> +          <para> +            As a special exception, if a desktop entry in a directory contains  +            a <varname>Categories</varname> field, that desktop entry should  +            <emphasis>not</emphasis> 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. +          </para> +        </listitem> +        <listitem> +          <para> +            If the legacy directory contains a ".directory" file, then  +            a <Directory> element should be generated that points to said  +            ".directory" file.  +          </para> +        </listitem> +        <listitem> +          <para> +            Legacy desktop entries should not be assigned any +            <varname>Categories</varname> 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>.) +          </para> +        </listitem> +      </itemizedlist> +    </para> +    <para> +      For example, say we have the following legacy directory hierarchy: +      <informalexample> +        <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 +        </programlisting> +      </informalexample> +      Conceptually that is converted to the following <Menu>: +      <informalexample> +        <programlisting> +          <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" +          "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd"> + +          <Menu> +            <AppDir>/usr/share/applnk</AppDir> +            <DirectoryDir>/usr/share/applnk</DirectoryDir> +            <Directory>.directory</Directory> +            <Include> +              <Filename>bar.desktop</Filename> +            </Include> +            <Menu> +              <Name>System</Name> +              <Directory>System/.directory</Directory> +              <Include> +                <Filename>System/foo.desktop</Filename> +              </Include> +            </Menu> +          </Menu> +        </programlisting> +      </informalexample> +      This <Menu> is then merged as if it were in a file  +      and loaded with <MergeFile>. +    </para> +  </sect1> + +  <sect1 id="example"> +    <title>Example Menu File</title> +    <para> +      <informalexample> +        <programlisting> +          <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" +          "http://www.freedesktop.org/standards/menu-spec/1.0/menu.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> + +            <-- some random moves, maybe to clean up legacy dirs,  +                   maybe from menu editing --> +            <Move> +              <Old>Foo</Old> +              <New>Bar</New> +              <Old>Faz/Abc</Old> +              <New>Baz/Xyz</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> +        </programlisting> +      </informalexample> +    </para> +  </sect1> + +  <appendix id="category-registry"> +    <title>Registered Categories</title> +    <para> +      Remember, these are case-sensitive. +      <informaltable> +        <tgroup cols="2"> +          <thead> +            <row> +              <entry>Category</entry> +              <entry>Description</entry> +            </row> +          </thead> +          <tbody> +            <row> +              <entry>Legacy</entry>  +              <entry>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>.</entry> + +            </row><row> +              <entry>Core</entry> +              <entry>Important application, core to the desktop such as a filemanager or a help browser</entry> + +            </row><row> +              <entry>Applet</entry> +              <entry>An applet that will run inside a panel or another such application, likely desktop specific</entry> + +            </row><row> +              <entry>TrayIcon</entry> +              <entry>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)</entry> + +            </row><row> +              <entry>Screensaver</entry> +              <entry>A screensaver (launching this desktop entry should activate the screensaver)</entry> + +            </row><row> +              <entry>TerminalEmulator</entry> +              <entry>A terminal emulator application.</entry> + +            </row><row> +              <entry>Development</entry> +              <entry>An application for development</entry> + +            </row><row> +              <entry>GUIDesigner</entry> +              <entry>A GUI designer application</entry> + +            </row><row> +              <entry>IDE</entry> +              <entry>IDE application</entry> + +            </row><row> +              <entry>TextEditor</entry> +              <entry>A text editor</entry> + +            </row><row> +              <entry>Office</entry> +              <entry>An office type application</entry> + +            </row><row> +              <entry>Spreadsheet</entry> +              <entry>A spreadsheet</entry> + +            </row><row> +              <entry>WordProcessor</entry> +              <entry>A word processor</entry> + +            </row><row> +              <entry>Presentation</entry> +              <entry>Presentation software</entry> + +            </row><row> +              <entry>Calendar</entry> +              <entry>Calendar app</entry> + +            </row><row> +              <entry>Email</entry> +              <entry>Email application</entry> + +            </row><row> +              <entry>TODO</entry> +              <entry>TODO list application</entry> + +            </row><row> +              <entry>ProjectManagement</entry> +              <entry>Project management application</entry> + +            </row><row> +              <entry>Graphics</entry> +              <entry>Graphical application</entry> + +            </row><row> +              <entry>VectorGraphics</entry> +              <entry>Vector based graphical application (should also include 'Graphics' category)</entry> + +            </row><row> +              <entry>RasterGraphics</entry> +              <entry>Raster based graphical application (should also include 'Graphics' category)</entry> + +            </row><row> +              <entry>System</entry> +              <entry>System application, "System Tools" such as say a log viewer or network monitor.</entry> + +            </row><row> +              <entry>SystemSetup</entry> +              <entry>System setup application, hardware installation, hardware clock setup, kernel setup, X server setup, etc.; i.e. system configuration tools. +              </entry> + +            </row><row> +              <entry>PackageManager</entry> +              <entry>A package manager application, should include the System keyword as well</entry> + +            </row><row> +              <entry>Utility</entry> +              <entry>Small utility application, "Accessories"</entry> + +            </row><row> +              <entry>Settings</entry> +              <entry>Desktop settings applications (not system settings application, those should be System;SystemSetup;)</entry> + +            </row><row> +              <entry>AdvancedSettings</entry> +              <entry>Advanced desktop settings.</entry> + +            </row><row> +              <entry>Accessibility</entry> +              <entry>Accessibility settings</entry> + +            </row><row> +              <entry>Network</entry> +              <entry>Network application such as a webbrowser</entry> + +            </row><row> +              <entry>Clock</entry> +              <entry>A clock application/applet</entry> + +            </row><row> +              <entry>Monitor</entry> +              <entry>Monitor application/applet that monitors some resource or activity.</entry> + +            </row><row> +              <entry>AudioVideo</entry> +              <entry>A multimedia (audio/video) application</entry> + +            </row><row> +              <entry>Amusement</entry> +              <entry>A simple amusement</entry> + +            </row><row> +              <entry>Emulator</entry> +              <entry>Emulator of another platform, such as a DOS emulator.</entry> + +            </row><row> +              <entry>Game</entry> +              <entry>A game</entry> + +            </row><row> +              <entry>3DGame</entry> +              <entry>A game in 3D</entry> + +            </row><row> +              <entry>ArcadeGame</entry> +              <entry>Arcade style game</entry> + +            </row><row> +              <entry>BoardGame</entry> +              <entry>A board game</entry> + +            </row><row> +              <entry>CardGame</entry> +              <entry>A card game</entry> + +            </row><row> +              <entry>FirstPersonGame</entry> +              <entry>First person perspective game</entry> + +            </row><row> +              <entry>PlatformGame</entry> +              <entry>Platform style game</entry> + +            </row><row> +              <entry>PuzzleGame</entry> +              <entry>Puzzle game</entry> + +            </row><row> +              <entry>SportsGame</entry> +              <entry>Sports game</entry> + +            </row><row> +              <entry>StrategyGame</entry> +              <entry>Strategy game</entry> + +            </row><row> +              <entry>BlocksGame</entry> +              <entry>Falling blocks game</entry> + +            </row><row> +              <entry>Education</entry> +              <entry>Educational software</entry> + +            </row><row> +              <entry>Math</entry> +              <entry>Math software</entry> + +            </row><row> +              <entry>Astronomy</entry> +              <entry>Astronomy software</entry> + +            </row><row> +              <entry>Physics</entry> +              <entry>Physics software</entry> + +            </row><row> +              <entry>Chemistry</entry> +              <entry>Chemistry software</entry> + +            </row><row> +              <entry>Science</entry> +              <entry>Scientific software</entry> + +            </row><row> +              <entry>HamRadio</entry> +              <entry>HAM radio software</entry> + +            </row><row> +              <entry>KDE</entry> +              <entry>Application based on KDE libraries.</entry> + +            </row><row> +              <entry>GNOME</entry> +              <entry>Application based on GNOME libraries.</entry> + +            </row><row> +              <entry>GTK</entry> +              <entry>Application based on GTK+ libraries (may also have GNOME category).</entry> + +            </row><row> +              <entry>Qt</entry> +              <entry>Application based on Qt libraries (may also have KDE category).</entry> + +            </row><row> +              <entry>Motif</entry> +              <entry>Application based on Motif libraries.</entry> + +            </row><row> +              <entry>ConsoleOnly</entry> +              <entry>Application that only works inside a terminal (text-based or command line application).</entry> + +            </row><row> +              <entry>Shell</entry> +              <entry>A shell (an actual specific shell such as +              <filename>bash</filename> or <filename>tcsh</filename>, not a +              TerminalEmulator).</entry> + +            </row> +          </tbody> +        </tgroup> +      </informaltable> + +    </para> +  </appendix> +  <appendix id="onlyshowin-registry"> +    <title>Registered OnlyShowIn Environments</title> +    <para> +      Remember, these are case-sensitive. "KDE" not "kde" should be  +      used. +      <informaltable> +        <tgroup cols="2"> +          <thead> +            <row> +              <entry>OnlyShowIn Value</entry> +              <entry>Environment</entry> +            </row> +          </thead> +          <tbody> +            <row> +              <entry>GNOME</entry><entry>GNOME Desktop</entry> +            </row><row> +              <entry>KDE</entry><entry>KDE Desktop</entry> +            </row><row> +              <entry>ROX</entry><entry>ROX Desktop</entry> +            </row><row> +              <entry>XFCE</entry><entry>XFCE Desktop</entry> +            </row><row> +              <entry>Old</entry><entry>Legacy menu systems</entry> +            </row> +          </tbody> +        </tgroup> +      </informaltable> +    </para> +  </appendix> +  <appendix id="third-party-howto"> +    <title>How to add your application to the menus</title> +    <para> +      The short answer for third party applications is: +      <itemizedlist> +        <listitem> +          <para> +            Install desktop entries to +            <replaceable>datadir</replaceable>/applications/ for each menu +            item. Please namespace the filename, as in "vendor-foo.desktop", or +            use a subdirectory of +            <replaceable>datadir</replaceable>/applications/ so you have +            "vendor/foo.desktop." Please be sure all desktop entries are valid +            (see the <ulink +            url="http://www.freedesktop.org/software/desktop-file-utils/"> +            desktop-file-utils</ulink> package for a validation utility). +          </para> +        </listitem> +        <listitem> +          <para> +            Install an XML menu file to <replaceable>sysconfdir</replaceable>/desktop/menus/applications-merged/ to add any submenus, if your desktop entries aren't already  +            included in some common categories. +          </para> +        </listitem> +        <listitem> +          <para> +            Install any directory entries needed for your submenus to <replaceable>datadir</replaceable>/desktop-directories/, taking care to namespace and validate +            the directory entries. +          </para> +        </listitem> +      </itemizedlist> +    </para> +    <para> +      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: +      <itemizedlist> +        <listitem> +          <para> +            If you add a <varname>Categories</varname> 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 <varname>Categories</varname> 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. +          </para> +        </listitem> +        <listitem> +          <para> +            If you add the line <literal>OnlyShowIn=Old;</literal> to a desktop +            entry, then old legacy implementations that ignore +            <varname>OnlyShowIn</varname> will still show the desktop entry, but +            implementations of this specification will not. Thus you can  +            add an "<literal>OnlyShowIn=Old;</literal>" entry to the legacy  +            hierarchy, and a new-style desktop entry to  +            <replaceable>datadir</replaceable>/applications/, and still get  +            only one entry in the menus. +          </para> +        </listitem> +      </itemizedlist> +    </para> +  </appendix> +  <appendix id="implementation-notes"> +    <title>Implementation notes</title> +    <sect1 id="menu-editing"> +      <title>Menu editing</title> +      <para> +        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 +        <literal><Exclude><Filename>foo.desktop</Filename></Exclude></literal>. If +        the user adds a menu item, you use +        <literal><Include><Filename>foo.desktop</Filename></Include></literal>. +      </para> +      <para> +        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 <emphasis>into</emphasis> the folder being +        moved to instead move things into the folder's new location. +      </para> +      <para> +        To delete a folder, simply append the <Deleted> element. +      </para> +      <para> +        Menu editors probably need to do some kind of consolidation/compression  +        to avoid an XML tree that grows infinitely over time. +      </para> +    </sect1> +  </appendix> +  <glossary><title>Glossary</title> +    <para> +      This glossary defines some of the terms used in this specification. +    </para> +       +    <glossentry id="term-desktop-entry"><glossterm>Desktop entry</glossterm> +      <glossdef> +        <para> +          A desktop entry is a file with a name ending in the ".desktop" +          extension which conforms to the <ulink +		  url="http://www.freedesktop.org/standards/desktop-entry-spec/">desktop +          entry specification</ulink>. 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." +        </para> +      </glossdef> +    </glossentry> + +    <glossentry id="term-directory-entry"><glossterm>Directory entry</glossterm> +      <glossdef> +        <para> +          A directory entry is a file with a name ending in the ".directory" +          extension which conforms to the <ulink +		  url="http://www.freedesktop.org/standards/desktop-entry-spec/">desktop +          entry specification</ulink>. It describes gives a localized name and  +          an icon for a submenu. +          Directory entries are also known as ".directory files." +        </para> +      </glossdef> +    </glossentry> + +    <glossentry id="term-menu-path"><glossterm>Menu path</glossterm> +      <glossdef> +        <para> +          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. +        </para> +      </glossdef> +    </glossentry> + +    <glossentry id="term-relative-path"><glossterm>Relative path</glossterm> +      <glossdef> +        <para> +          The canonical path to a desktop or directory entry, relative to the +          <AppDir> or <DirectoryDir> containing the +          entry. For example, if <filename>/usr/share/applications</filename> is +          specified as an <AppDir>, the relative path to +          <filename>/usr/share/applications/foo/bar.desktop</filename> is +          <filename>foo/bar.desktop</filename>. +        </para> +      </glossdef> +    </glossentry> +  </glossary> +</article> + diff --git a/systemtray/systemtray-spec.xml b/systemtray/systemtray-spec.xml new file mode 100644 index 0000000..b5f1568 --- /dev/null +++ b/systemtray/systemtray-spec.xml @@ -0,0 +1,342 @@ +<?xml version="1.0"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"  +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [ +]> +<article id="index"> +  <articleinfo> +    <title>System Tray Protocol Specification</title> +    <releaseinfo>Version 0.1</releaseinfo> +    <date>19 September 2002</date> +    <authorgroup> +      <author> +	<firstname>Havoc</firstname> +	<surname>Pennington</surname> +	<affiliation> +	  <address> +	    <email>hp@redhat.com</email> +	  </address> +	</affiliation> +      </author> +    </authorgroup> +  </articleinfo> + +  <sect1 id="overview"> +    <title>Overview</title> +    <para> +     The "system tray" is an application running on a given X screen +     that can display small icons provided by running +     applications. Windows XP calls this feature the "notification area." +     <footnote><para>According to the MSDN documentation for the +     <literal>Shell_NotifyIcon()</literal> function, +     "The taskbar notification area is sometimes erroneously called +     the 'tray.'" So presumably "notification area" is the official +     term on Windows. Parts of the docs also call it the "status +     area."</para></footnote> Inspired by KDE, this specification  +     uses the term "system tray." +    </para> +    <para> +     From a UI standpoint, the system tray is normally used for +     transient icons that indicate some special state, while +     full-blown "applets" are used for permanent dock/panel +     features. For example, a system tray icon might appear to tell +     the user that they have new mail, or have an incoming instant +     message, or something along those lines. +    </para> +    <para> +     The basic idea is that creating an icon in the notification  +     area is less annoying than popping up a dialog. However it's  +     also harder to notice, so Windows XP adds a feature allowing +     tray icons to pop up small message balloons. (Users can disable +     these via a hidden registry setting.) This specification  +     also supports the balloon feature. +    </para> +  </sect1> + +  <sect1 id="definitions"> +    <title>Definitions</title> +    <variablelist> +      <varlistentry> +	<term>System tray</term> +	<listitem> +	  <para> +            The system tray is an X client which owns a special  +            manager selection on a given screen and provides +            container windows. +	  </para> +	</listitem> +      </varlistentry> +      <varlistentry> +	<term>Selection owner window</term> +	<listitem> +	  <para> +            The selection owner window is the window belonging to the +            System Tray that owns the manager selection (as in +            <literal>XGetSelectionOwner()</literal>/<literal>XSetSelectionOwner()</literal>. +            Note that this probably is not the same window that's used  +            to contain the system tray icons. +	  </para> +	</listitem> +      </varlistentry> +      <varlistentry> +	<term>Tray icon</term> +	<listitem> +	  <para> +            The tray icon is a window to be embedded in the +            system tray. +	  </para> +	</listitem> +      </varlistentry> +    </variablelist> +  </sect1> + +  <sect1 id="locating"> +    <title>Locating the system tray</title> +    <para> +      On startup, the system tray must acquire a manager selection +      called <literal>_NET_SYSTEM_TRAY_Sn</literal>, replacing +      <literal>n</literal> with the screen number the tray wants to +      use. The conventions for manager selections are defined in the  +      ICCCM. +    </para> +    <para> +      Because the selection owner window should be destroyed when the +      manager selection is lost, normally the selection owner window +      will not be the same as any of the user-visible windows provided +      by the system tray. +    </para> +    <para> +      A system tray that fails to get the selection or loses the  +      selection should assume that another system tray is running,  +      and let the selection owner handle tray icons. +    </para> +    <para> +      An application wishing to provide an icon to the system tray +      should first locate the system tray by requesting the owner +      window of the manager selection. If the manager selection has no +      owner, clients may use the method described in the ICCCM +      (watching for a <literal>MANAGER</literal> client message) to be +      notified when a system tray appears.  +    </para> +  </sect1> + +  <sect1 id="messages"> +    <title>Opcode messages</title> +      <para> +        Tray icons can send "opcodes" to  +        the system tray. These are X client messages, sent with +        <literal>NoEventMask</literal>, a +        <literal>message_type</literal> of +        <literal>_NET_SYSTEM_TRAY_OPCODE</literal>, and format 32.  +        The first data field in the message is a timestamp (the stamp +        of the current event, if available, otherwise CurrentTime). +        The second data field is an integer indicating the op code  +        of the message: +         <programlisting> +#define SYSTEM_TRAY_REQUEST_DOCK    0 +#define SYSTEM_TRAY_BEGIN_MESSAGE   1 +#define SYSTEM_TRAY_CANCEL_MESSAGE  2 +         </programlisting> +        The content remaining three data fields depends on the type of +        message being sent. If they are unused by a particular +        message, they should always be set to 0. +      </para> +      <para>  +        Here is an example of how to send a client message: +      <programlisting><!-- +-->#include <X11/Xlib.h> + +void send_message( +     Display* dpy, /* display */ +     Window w,     /* sender (tray icon window) */ +     long message, /* message opcode */ +     long data1    /* message data 1 */ +     long data2    /* message data 2 */ +     long data3    /* message data 3 */ +){ +    XEvent ev; +   +    memset(&ev, 0, sizeof(ev)); +    ev.xclient.type = ClientMessage; +    ev.xclient.window = w; +    ev.xclient.message_type = XInternAtom (dpy, "_NET_SYSTEM_TRAY_OPCODE", False ); +    ev.xclient.format = 32; +    ev.xclient.data.l[0] = x_time; +    ev.xclient.data.l[1] = message; +    ev.xclient.data.l[2] = data1; +    ev.xclient.data.l[3] = data2; +    ev.xclient.data.l[4] = data3; + +    trap_errors(); +    XSendEvent(dpy, w, False, NoEventMask, &ev); +    XSync(dpy, False); +    if (untrap_errors()) { +	/* Handle failure */ +    } +}<!-- +    --></programlisting> + +     </para> + +  </sect1> + +  <sect1 id="docking"> +    <title>Docking a tray icon</title> +    <para> +      A tray icon must support the "client" or "plug" side of the +      XEMBED specification. XEMBED is a protocol for cross-toolkit +      widget embedding. +    </para> +    <para> +      To begin the docking process, the tray icon application sends +      a client message event to the manager selection owner window,  +      as described in <xref linkend="messages"/>. This event  +      should contain the <literal>SYSTEM_TRAY_REQUEST_DOCK</literal> +      opcode, <literal>xclient.data.l[2]</literal> should contain  +      the X window ID of the tray icon to be docked. +    </para> +    <para> +      At this point the "embedding life cycle" explained in the XEMBED +      specification begins. The XEMBED specification explains how the  +      embedding application will interact with the embedded tray  +      icon, and how the embedder/embedded relationship may be ended. +    </para> +    <para> +      Tray icons may be assigned any size by the system tray, and  +      should do their best to cope with any size effectively. +    </para> +  </sect1> + +  <sect1 id="hints"> +    <title>Tray icon hints</title> +    <para> +     Tray icons should set the following hints to help the system  +     tray provide a nice user interface. The name and icon hints  +     are used if the system tray needs to refer to a tray icon; +     for example, the system tray may present a list of tray  +     icons and let the user reorder them or change their properties. +    </para> + +    <sect2><title>_NET_WM_NAME</title> +      <programlisting><![CDATA[ +_NET_WM_NAME, UTF8_STRING +]]></programlisting> +	<para> +         This hint should be set as it would be for a normal toplevel +         window, as defined in the Extended Window Manager Hints +         Specification (EWMH).  The hint MUST be in UTF-8 encoding. It +         provides a human-readable, localized name for the tray icon. +	</para> +    </sect2> + +    <sect2><title>WM_CLASS</title> +      <programlisting><![CDATA[ +WM_CLASS, STRING +]]></programlisting> +	<para> +         This hint should be set as it would be for a normal toplevel +         window, as defined in the ICCCM. The system tray can use it +         to distinguish different kinds of tray icon. This is useful +         for example if the system tray wants to save and restore the +         positions of the icons in the tray. +	</para> +    </sect2> + +	<sect2> +		<title>_NET_WM_ICON</title> +		<programlisting><![CDATA[ +_NET_WM_ICON CARDINAL[][2+n]/32 +]]></programlisting> +		<para> +         This hint should be set as it would be for a normal toplevel +         window, as defined in the Extended Window Manager Hints +         Specification (EWMH). See that specification for the format +         of the icon data. +		</para> +	</sect2> + +  </sect1> + +  <sect1 id="balloon"> +    <title>Balloon messages</title> +    <para> +      Tray icons may ask the system tray to display a balloon message  +      to the user. The system tray coordinates balloon messages  +      to ensure that they have a consistent look-and-feel, and to  +      avoid displaying multiple balloon messages at once. +    </para> +    <para> +      A balloon message is a short text message to be displayed to  +      the user. The message may have a timeout; if so, the message +      will be taken down after the timeout expires. Messages are +      displayed in a queue, as only one can appear at a time;  +      if a message has a timeout, the timer begins when the message +      is first displayed. Users may be allowed to close messages at +      any time, and may be allowed to disable all message display. +    </para> +    <para> +      System trays may display balloon messages in any way they  +      see fit; for example, instead of popping up a balloon, they  +      could choose to put a special indicator around icons with  +      pending messages, and display the message on mouseover. +    </para> +    <para> +      Balloon messages are sent from the tray icon to the system tray +      selection owner window as a series of client messages. The first +      client message is an opcode message, and contains the usual timestamp, +      and the op code <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal>. +      <literal>xclient.data.l[2]</literal> contains the timeout in +      thousandths of a second or zero for infinite timeout, +      <literal>xclient.data.l[3]</literal> contains the length  +      of the message string in bytes, not including any nul bytes, and  +      <literal>xclient.data.l[4]</literal> contains an ID number +      for the message. This ID number should never be reused by  +      the same tray icon. (The simplest way to generate the ID number  +      is to increment it with each message sent.) +    </para> +    <para> +      Following the <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal> +      op code, the tray icon should send a series of client messages +      with a <literal>message_type</literal> of +      <literal>_NET_SYSTEM_TRAY_MESSAGE_DATA</literal>. These client +      messages must have their <literal>window</literal> field set  +      to the window ID of the tray icon, and have a +      <literal>format</literal> of 8. +    </para> +    <para> +      Each <literal>_NET_SYSTEM_TRAY_MESSAGE_DATA</literal> message +      contains 20 bytes of the message string, up to the length given  +      in the <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal> opcode. +      If the message string is zero-length, then no messages need be +      sent beyond the <literal>SYSTEM_TRAY_BEGIN_MESSAGE</literal>.  +      A terminating nul byte should never be sent. +    </para> +    <para> +      System trays may receive portions of messages from several  +      tray icons at once, so are required to reassemble the messages +      based on the window ID of the tray icon. +    </para> +    <para> +      The tray icon may wish to cancel a previously-sent balloon +      message. To do so, it sends a +      <literal>SYSTEM_TRAY_CANCEL_MESSAGE</literal> opcode with +      <literal>data.l[2]</literal> set to the ID number of the message +      to cancel. +    </para> +  </sect1> + +  <appendix id="changes"> +    <title>Change history</title> +    <formalpara> +      <title>Version 0.1, 20 April 2002, Havoc Pennington</title>     +      <para> +	<itemizedlist> +	  <listitem> +	    <para> +              Created initial draft. +	    </para> +	  </listitem> +	</itemizedlist> +      </para> +    </formalpara> +  </appendix> +</article> | 
