In the process of building Velen Sight, I learned some basics on adding menu entries to linux desktop installations.

Menu entries on an XDG compatible system use the following types of files:

  • Desktop entries
  • Directory entries
  • Menu files

And the following helper programs:

  • xdg-desktop-menu
  • kbuildsycoca5 (KDE only)

The files

Desktop entries

These files, ending in .desktop, are used to declare a single entry in the application menu. Below is a simple example of YourApp-test.desktop

[Desktop entry]
Type=Application
Name=Your App
Comment=My cool app
Exec=yourbin --option
Categories=Game;Internet

Fields

  • Type - required to be “Application” for a desktop entry file
  • Name - the name your entry will have in the menu
  • Comment - optional field to display additional data about your app
  • Exec - the line containing the command to be run when your menu item is clicked
  • Categories - optional field semicolon-separated list of categories to list your menu entry under. The full list of categories can be found here

Directory entries

These files, ending in .directory, are used for constructing nested submenus in an application menu. They essentially just contain the folder name of a current submenu level. If you use a directory entry file, don’t include any categories in your desktop entry file. Below is an example of YourApp-dir.desktop

[Desktop entry]
Type=Directory
Name=Your App Folder

Fields

  • Type - required to be “Directory” for a directory entry file
  • Name - the name your folder will have in the menu

The way these directory entries get linked together is through the next file type, the menu file.

These are XML files that are typically created by the XDG system (via xdg-desktop-menu) to represent the desktop and directory entry contents in a hierarchy. They contain references to the directory and desktop entries, describing the layout you’ve specified. For example:

<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd">
<!-- Do not edit manually - generated and managed by xdg-desktop-menu -->
<Menu>
    <Name>Applications</Name>
    <Menu>
        <Name>YourApp-test</Name>
        <Include>
            <Filename>YourApp-test.desktop</Filename>
        </Include>
    </Menu>
</Menu>

This file essentially creates a single menu entry, whose details are listed in YourApp-test.desktop. A more elaborate menu file could include multiple layers of menus:

<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd">
<!-- Do not edit manually - generated and managed by xdg-desktop-menu -->
<Menu>
    <Name>Applications</Name>
    <Menu>
        <Directory>YourApp-top.directory</Directory>
        <Name>YourApp-top</Name>
        <Menu>
            <Directory>YourApp-second.directory</Directory>
            <Name>YourApp-second</Name>
            <Include>
                <Filename>YourApp-test.desktop</Filename>
            </Include>
        </Menu>
    </Menu>
</Menu>

This file creates 2 layers of folders in the menu and finally adds an entry to your app as the leaf node. So it looks something like this: Root (Applications) > Top Directory > Second Directory > Your App

XDG directories

The following notable directories exist on an XDG system to store the files related to an XDG menu:

  • ~/.local/share/applications
  • $XDG_DATA_HOME/applications

This is where .desktop entries get stored.

  • ~/.local/share/desktop-directories
  • $XDG_DATA_HOME/desktop-directories

This is where .directory entries get stored.

  • ~/.config/menus/applications-merged
  • $XDG_CONFIG_HOME/menus/applications-merged

This is where .menu files are built.

Helper programs

xdg-desktop-menu

This is a helper program which takes desktop files, directory files, or both. It validates and installs them in their correct location and then generates the menu file in the correct location. Finally, it optionally refreshes the XDG system so that your changes show up immediately. Everything that is done with this helper can be done manually.

Typically it is used to create a menu file from a directory file and a desktop file(s):

xdg-desktop-menu install YourApp-dir.directory YourApp-test.desktop

The above command will construct the following .menu file:

<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd">
<!-- Do not edit manually - generated and managed by xdg-desktop-menu -->
<Menu>
    <Name>Applications</Name>
    <Menu>
        <Name>YourApp-test</Name>
        <Directory>YourApp-dir.directory</Directory>
        <Include>
            <Filename>YourApp-test.desktop</Filename>
        </Include>
    </Menu>
</Menu>

For more elaborate menu files, you may wish to construct and install the menu file by hand.

kbuildsycoca5

For KDE only, this file refreshes the binary cache of all of the XDG menu entry files. This is useful to call when testing out your entries, otherwise you will have to wait for the XDG system to refresh itself.

File naming

xdg-desktop-menu prefers if your directory and desktop files have a vendor name prefixing the file. This name is terminated by a -. For example, in the file named YourApp-test.desktop, the vendor name is YourApp. This name is purely to prevent file collisions, and can be omitted, providing you run xdg-desktop-menu with the --novendor option.

Building a menu by hand

As stated earlier, you don’t need xdg-desktop-menu to create menu entries manually. In fact, you often don’t even need .directory files, even to do complex nested directories. Below is an example of a .menu file containing 2 levels of folders, but no directory files:

<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN" "http://www.freedesktop.org/standards/menu-spec/menu-1.0.dtd">
<!-- Do not edit manually - generated and managed by xdg-desktop-menu -->
<Menu>
    <Name>Applications</Name>
    <Menu>
        <Name>Top Directory</Name>
        <Menu>
            <Name>Second Directory</Name>
            <Include>
                <Filename>YourApp-test.desktop</Filename>
            </Include>
        </Menu>
    </Menu>
</Menu>

This constructs entries like this: Root (Applications) > Top Directory > Second Directory > Your App. Notice how, if we don’t use a <Directory> element, pointing to a .directory file, the XDG menu system uses the <Name> element when listing the menu folders, instead of pulling the Name= field from the .directory file.