1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
|
<!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>Desktop Menu Specification</title>
<releaseinfo>Version 0.9</releaseinfo>
<date>8 December 2004</date>
<authorgroup>
<author>
<firstname>Waldo</firstname>
<surname>Bastian</surname>
<affiliation>
<address>
<email>bastian@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>
<author>
<firstname>Heinrich</firstname>
<surname>Wendel</surname>
<affiliation>
<address>
<email>h_wendel@cojobo.net</email>
</address>
</affiliation>
</author>
</authorgroup>
</articleinfo>
<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">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>
<para>
In addition to a strict definition of the contents of each menu this
specification also foresees in a number of layout / presentation hints.
This part of the specification is optional, implementations may chose to
ignore these hints.
</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 system wide one.
(Though the user's menu may explicitly merge the system wide 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>
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 three new fields to <ulink
url="http://www.freedesktop.org/standards/desktop-entry-spec">desktop
entries</ulink>: <varname>Categories</varname>,
<varname>OnlyShowIn</varname> and <varname>NotShowIn</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>
<para>
The <varname>NotShowIn</varname> field is a list of strings identifying
the environments that should not display a given menu item. If an
<varname>NotShowIn</varname> field is present, a given environment should
only display the menu item if the string identifying that environment is
not present. The strings are case-sensitive. <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>Document Type 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 0.8</term>
<listitem>
<para>
<literal>PUBLIC "-//freedesktop//DTD Menu 0.8//EN"</literal>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>System Identifier for 0.8</term>
<listitem>
<para>
<literal>http://www.freedesktop.org/standards/menu-spec/menu-0.8.dtd</literal>
</para>
</listitem>
</varlistentry>
</variablelist>
Here is a sample document type declaration:
<informalexample>
<programlisting>
<!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 0.8//EN"
"http://www.freedesktop.org/standards/menu-spec/menu-0.8.dtd">
</programlisting>
</informalexample>
All menu files MUST include the document type 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.
Only files ending in ".desktop" should be used, other files are
ignored.
</para>
<para>
Desktop entries in the pool of available entries are identified
by their <firstterm>desktop-file id</firstterm> (see <xref
linkend="term-desktop-file-id"/>).
The desktop-file id of a desktop entry is equal to its filename,
with any path components removed.
So given a <AppDir>
<filename>/foo/bar</filename> and desktop entry
<filename>/foo/bar/Hello.desktop</filename> the desktop
entry would get a desktop-file id of <filename>Hello.desktop</filename>
</para>
<para>
If the directory contains sub-directories then these sub-directories
should be (recursively) scanned as well. The name of the subdirectory
should be added as prefix to the desktop-file id together with a dash character ("-")
So given a <AppDir>
<filename>/foo/bar</filename> and desktop entry
<filename>/foo/bar/booz/Hello.desktop</filename> the desktop
entry would get a desktop-file id of <filename>booz-Hello.desktop</filename>
A desktop entry <filename>/foo/bar/bo/oz/Hello.desktop</filename> would result
in a desktop-file id of <filename>bo-oz-Hello.desktop</filename>
</para>
<para>
<AppDir> elements appearing later in the menu file have
priority in case of collisions between desktop-file ids.
</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.
</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 meta information
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 as allocated according
to whether it was matched by an <Include> rule 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 marked as allocated 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
desktop-file id. See <xref linkend="term-desktop-file-id"/>.
</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 get a desktop-file id of <filename>Hello.desktop</filename>.
Given a prefix of <literal>boo-</literal>, it would instead be
assigned the desktop-file id <filename>boo-Hello.desktop</filename>.
The prefix should not 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 with a hard coded prefix of "kde-".
When expanding <KDELegacyDirs> to a list of <LegacyDir>, the
locations that are earlier in the search path go later in the
<Menu> so that they have priority.
The search path can be obtained by running <filename>kde-config --path apps</filename>
</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>
<varlistentry>
<term><Layout></term>
<listitem>
<para>
The <Layout> element is an optional part of this specification.
Implementations that do not support the <Layout> element should
preserve any <Layout> elements and their contents as far as
possible.
Each <Menu> may optionally contain a <Layout> element.
If multiple elements appear then only the last such element is relevant.
The purpose of this element is to offer suggestions for the presentation
of the menu.
If a menu does not contain a <Layout> element or if it contains
an empty <Layout> element then the default layout should be used.
The <Layout> element may contain <Filename>, <Menuname>,
<Separator> and <Merge> elements. The <Layout> element
defines a suggested layout for the menu starting from top to bottom.
References to desktop entries that are not contained in this
menu as defined by the <Include> and <Exclude> elements should
be ignored. References to sub-menus that are not directly contained in this
menu as defined by the <Menu> elements should be ignored.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><DefaultLayout [show_empty="false"] [inline="false"] [inline_limit="4"] [inline_header="true"] [inline_alias="false"]></term>
<listitem>
<para>
The <DefaultLayout> element is an optional part of this specification.
Implementations that do not support the <DefaultLayout> element should
preserve any <DefaultLayout> elements and their contents as far as
possible.
Each <Menu> may optionally contain a <DefaultLayout> element
which defines the default-layout for the current menu and all its sub-menus.
If a menu has a <DefaultLayout> element then this will override
any default-layout specified by a parent menu.
The default-layout defines the suggested layout if a <Menu> element
does either not have <Layout> element or if it has an empty <Layout> element.
For explanations of the various attributes see the <Menuname> element.
If no default-layout has been specified then the layout as specified by the following
elements should be assumed:
<DefaultLayout show_empty="false" inline="false" inline_limit="4" inline_header="true" inline_alias="false"><Merge type="menus"/><Merge type="files"/></DefaultLayout>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><Menuname [show_empty="..."] [inline="..."] [inline_limit="..."] [inline_header="..."] [inline_alias="..."]></term>
<listitem>
<para>
This element may only appear as a child of a <Layout> or <DefaultLayout>
menu. Its contents references an immediate sub-menu of the current menu as defined
with the <Menu> element, as such it should never contain a slash.
If no such sub-menu exists the element should be ignored.
This element may have various attributes, the default values are taken from the DefaultLayout key.
The show_empty attribute defines whether a menu that contains no desktop
entries and no sub-menus should be shown at all. The show_empty attribute
can be "true" or "false".
It may have an inline attribute that can be either "true" or "false".
If the inline attribute is "true" the menu that is referenced may be copied into the
current menu at the current point instead of being inserted as sub-menu of the current menu.
The optional inline_limit attribute defines the maximum number of entries that can be inlined.
If the sub-menu has more entries than inline_limit, the sub-menu will not be inlined.
If the inline_limit is 0 (zero) there is no limit.
The optional inline_header attribute defines whether an inlined menu should be preceded with
a header entry listing the caption of the sub-menu.
The inline_header attribute can be either "true" or "false".
The optional inline_alias attribute defines whether a single inlined entry should adopt the
caption of the inlined menu. In such case no additional header entry will be added regardless
of the value of the inline_header attribute.
The inline_alias attribute can be either "true" or "false".
Example: if a menu has a sub-menu titled "WordProcessor" with a single entry "OpenOffice 4.2",
and both inline="true" and inline_alias="true" are specified then this would result in the
"OpenOffice 4.2" entry being inlined in the current menu but the "OpenOffice 4.2" caption
of the entry would be replaced with "WordProcessor".
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><Separator></term>
<listitem>
<para>
This element may only appear as a child of a <Layout> or <DefaultLayout>
menu. It indicates a suggestion to draw a visual separator at this point in the menu.
<Separator> elements at the start of a menu, at the end of a menu or that directly
follow other <Separator> elements may be ignored.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><Merge type="menus"|"files"|"all"/></term>
<listitem>
<para>
This element may only appear as a child of a <Layout> or <DefaultLayout>
menu. It indicates the point where desktop entries and sub-menus that are not explicitly
mentioned within the <Layout> or <DefaultLayout> element are to be inserted.
It has a type attribute that indicates which elements should be inserted:
type="menus"
means that all sub-menus that are not explicitly mentioned should be inserted in
alphabetical order of their visual caption at this point.
type="files"
means that all desktop entries
contained in this menu that are not explicitly mentioned should be inserted in
alphabetical order of their visual caption at this point.
type="all" means that a mix of all sub-menus
and all desktop entries that are not explicitly mentioned should be inserted in
alphabetical order of their visual caption at this point.
Each <Layout> or <DefaultLayout> element shall have exactly one <Merge type="all">
element or it shall have exactly one <Merge type="files"> and exactly one
<Merge type="menus"> element. An exception is made for a completely empty <Layout>
element which may be used to indicate that the default-layout should be used instead.
</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 to remove duplicates:
<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>
Resolve duplicate <Move> operations (with the same
origin path) by keeping the last one.
</para>
</listitem>
<listitem>
<para>
Recurse into each child <Menu>, performing this list of
steps for each child in order.
</para>
</listitem>
</orderedlist>
</para>
<para>
After recursing once to remove duplicates, resolve <Move> elements
for each menu starting with the top level and recursing into child menus.
So the deepest menus have their <Move> operations performed last.
Within each <Menu>, execute <Move> operations in the order
that they appear. If the destination path does not exist, simply relocate
the origin <Menu> element, and change its <Name> field to
match the destination path. If the origin path does not exist, do
nothing. If both paths exist, take the origin <Menu> element,
delete its <Name> element, and prepend its remaining child elements
to the destination <Menu> element.
</para>
<para>
If any <Move> operations affect a menu, then re-run the
steps to resolve duplicates in case any duplicates have been
created.
</para>
<para>
Finally, for each <Menu> containing a <Deleted> element which
is not followed by a <NotDeleted> element, remove that menu and all
its child menus.
</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>
<para>
To prevent that a desktop entry from one party inadvertently cancels out
the desktop entry from another party because both happen to get the same
desktop-file id it is recommended that providers of desktop-files ensure that
all desktop-file ids start with a vendor prefix. A vendor prefix
consists of [a-zA-Z] and is terminated with a dash ("-"). Open Source
projects and commercial parties are encouraged to use a word or phrase,
preferably their name, as prefix for which they hold a trademark. Open Source
applications can also ask to make use of the vendor prefix of another open
source project (such as GNOME or KDE) they consider themselves affiliated
with, at the discretion of these projects.
</para>
<para>
For example, to ensure that GNOME applications start with a vendor prefix of "gnome-",
it could either add "gnome-" to all the desktop files it installs in
<filename><replaceable>datadir</replaceable>/applications/</filename> or it could
install desktop files in a <filename><replaceable>datadir</replaceable>/applications/gnome</filename>
subdirectory. When including legacy menu hierarchies the <literal>prefix</literal> argument
of the <LegacyDir> element can be used to specify a prefix.
</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 desktop-file id, the entry for the earlier (closer
to the top of the file) <AppDir> must be discarded. Next, add to the
pool the entries for any <AppDir>s specified by ancestor
<Menu> elements. If a parent menu has a duplicate entry (same
desktop-file id), the entry for the child menu has priority.
</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 and mark it as having been allocated.
For each <Exclude>, match the rules against the currently-included
desktop entries. For each desktop entry that matches, remove it again
from the menu. Note that an entry that is included in a menu but excluded
again by a later <Exclude> is still considered allocated (for the
purposes of <OnlyUnallocated>) even though that entry no longer
appears in the menu.
</para>
<para>
Two passes are necessary, once for regular menus where any entry may
be matched, and once for <OnlyUnallocated> menus where only entries
which have not been marked as allocated may be matched.
</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 0.8//EN"
"http://www.freedesktop.org/standards/menu-spec/menu-0.8.dtd">
<Menu>
<Name>Applications</Name>
<AppDir>/usr/share/applnk</AppDir>
<DirectoryDir>/usr/share/applnk</DirectoryDir>
<Directory>.directory</Directory>
<Include>
<Filename>bar.desktop</Filename>
</Include>
<Menu>
<Name>System</Name>
<AppDir>/usr/share/applnk/System</AppDir>
<DirectoryDir>/usr/share/applnk/System</DirectoryDir>
<Directory>.directory</Directory>
<Include>
<Filename>foo.desktop</Filename>
</Include>
</Menu>
</Menu>
</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 0.8//EN"
"http://www.freedesktop.org/standards/menu-spec/menu-0.8.dtd">
<Menu>
<Name>Applications</Name>
<Directory>Applications.directory</Directory>
<-- Search the default locations -->
<DefaultAppDirs/>
<DefaultDirectoryDirs/>
<-- Merge third-party submenus -->
<MergeDir>applications-merged</MergeDir>
<-- Merge legacy hierarchy -->
<LegacyDir>/usr/share/applnk</LegacyDir>
<-- Define default layout -->
<DefaultLayout>
<Merge type="menus"/>
<Merge type="files"/>
<Separator/>
<Menuname>More</Menuname>
</DefaultLayout>
<-- some random moves, maybe to clean up legacy dirs,
maybe from menu editing -->
<Move>
<Old>Foo</Old>
<New>Bar</New>
<Old>Foo2</Old>
<New>Bar2</New>
</Move>
<-- A preferences submenu, kept in a separate file
so it can also be used standalone -->
<Menu>
<Name>Preferences</Name>
<Directory>Preferences.directory</Directory>
<MergeFile>preferences.menu</MergeFile>
</Menu>
<-- An Office submenu, specified inline -->
<Menu>
<Name>Office</Name>
<Directory>Office.directory</Directory>
<Include>
<Category>Office</Category>
</Include>
<Exclude>
<Filename>foo.desktop</Filename>
</Exclude>
</Menu>
</Menu>
</programlisting>
</informalexample>
</para>
</sect1>
<appendix id="category-registry">
<title>Registered Categories</title>
<para>
Remember, these are case-sensitive.
When using a category described in the list below it is strongly
recommended to also include the category listed under Related
Categories. If a category has multiple related categories the most
suitable related category should be included.
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>Category</entry>
<entry>Description</entry>
<entry>Related Categories</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 file manager or a help browser</entry>
<entry></entry>
</row><row>
<entry>Development</entry>
<entry>An application for development</entry>
<entry></entry>
</row><row>
<entry>Building</entry>
<entry>A tool to build applications</entry>
<entry>Development</entry>
</row><row>
<entry>Debugger</entry>
<entry>A tool to debug applications</entry>
<entry>Development</entry>
</row><row>
<entry>IDE</entry>
<entry>IDE application</entry>
<entry>Development</entry>
</row><row>
<entry>GUIDesigner</entry>
<entry>A GUI designer application</entry>
<entry>Development</entry>
</row><row>
<entry>Profiling</entry>
<entry>A profiling tool</entry>
<entry>Development</entry>
</row><row>
<entry>RevisionControl</entry>
<entry>Applications like cvs or subversion</entry>
<entry>Development</entry>
</row><row>
<entry>Translation</entry>
<entry>A translation tool</entry>
<entry>Development</entry>
</row><row>
<entry>Office</entry>
<entry>An office type application</entry>
</row><row>
<entry>Calendar</entry>
<entry>Calendar application</entry>
<entry>Office</entry>
</row><row>
<entry>ContactManagement</entry>
<entry>E.g. an address book</entry>
<entry>Office</entry>
</row><row>
<entry>Database</entry>
<entry>Application to manage a database</entry>
<entry>Office or Development or AudioVideo</entry>
</row><row>
<entry>Dictionary</entry>
<entry>A dictionary</entry>
<entry>Office</entry>
</row><row>
<entry>Chart</entry>
<entry>Chart application</entry>
<entry>Office</entry>
</row><row>
<entry>Email</entry>
<entry>Email application</entry>
<entry>Office;Network</entry>
</row><row>
<entry>Finance</entry>
<entry>Application to manage your finance</entry>
<entry>Office</entry>
</row><row>
<entry>FlowChart</entry>
<entry>A flowchart application</entry>
<entry>Office</entry>
</row><row>
<entry>PDA</entry>
<entry>Tool to manage your PDA</entry>
<entry>Office</entry>
</row><row>
<entry>ProjectManagement</entry>
<entry>Project management application</entry>
<entry>Office;Development</entry>
</row><row>
<entry>Presentation</entry>
<entry>Presentation software</entry>
<entry>Office</entry>
</row><row>
<entry>Spreadsheet</entry>
<entry>A spreadsheet</entry>
<entry>Office</entry>
</row><row>
<entry>WordProcessor</entry>
<entry>A word processor</entry>
<entry>Office</entry>
</row><row>
<entry>Graphics</entry>
<entry>Graphical application</entry>
</row><row>
<entry>2DGraphics</entry>
<entry>2D based graphical application</entry>
<entry>Graphics</entry>
</row><row>
<entry>VectorGraphics</entry>
<entry>Vector based graphical application</entry>
<entry>2DGraphics</entry>
</row><row>
<entry>RasterGraphics</entry>
<entry>Raster based graphical application</entry>
<entry>2DGraphics</entry>
</row><row>
<entry>3DGraphics</entry>
<entry>3D based graphical application</entry>
<entry>Graphics</entry>
</row><row>
<entry>Scanning</entry>
<entry>Tool to scan a file/text</entry>
<entry>Graphics</entry>
</row><row>
<entry>OCR</entry>
<entry>Optical character recognition application</entry>
<entry>Scanning</entry>
</row><row>
<entry>Photography</entry>
<entry>Camera tools, etc.</entry>
<entry>Graphics or Office</entry>
</row><row>
<entry>Viewer</entry>
<entry>Tool to view e.g. a graphic or pdf file</entry>
<entry>Graphics or Office</entry>
</row><row>
<entry>Settings</entry>
<entry>Settings applications</entry>
</row><row>
<entry>DesktopSettings</entry>
<entry>Configuration tool for the GUI</entry>
<entry>Settings</entry>
</row><row>
<entry>HardwareSettings</entry>
<entry>A tool to manage hardware components, like sound cards, video cards or printers</entry>
<entry>Settings</entry>
</row><row>
<entry>PackageManager</entry>
<entry>A package manager application</entry>
<entry>Settings</entry>
</row><row>
<entry>Network</entry>
<entry>Network application such as a web browser</entry>
<entry>(Settings)</entry>
</row><row>
<entry>Dialup</entry>
<entry>A dial-up program</entry>
<entry>Network</entry>
</row><row>
<entry>InstantMessaging</entry>
<entry>An instant messaging client</entry>
<entry>Network</entry>
</row><row>
<entry>IRCClient</entry>
<entry>An IRC client</entry>
<entry>Network</entry>
</row><row>
<entry>FileTransfer</entry>
<entry>Tools like FTP or P2P programs</entry>
<entry>Network</entry>
</row><row>
<entry>HamRadio</entry>
<entry>HAM radio software</entry>
<entry>Network or Audio</entry>
</row><row>
<entry>News</entry>
<entry>A news reader or a news ticker</entry>
</row><row>
<entry>P2P</entry>
<entry>A P2P program</entry>
<entry>Network</entry>
</row><row>
<entry>RemoteAccess</entry>
<entry>A tool to remotely manage your PC</entry>
<entry>Network</entry>
</row><row>
<entry>Telephony</entry>
<entry>Telephony via PC</entry>
<entry>Network</entry>
</row><row>
<entry>WebBrowser</entry>
<entry>A web browser</entry>
<entry>Network</entry>
</row><row>
<entry>WebDevelopment</entry>
<entry>A tool for web developers</entry>
<entry>Network or Development</entry>
</row><row>
<entry>AudioVideo</entry>
<entry>A multimedia (audio/video) application</entry>
</row><row>
<entry>Audio</entry>
<entry>An audio application</entry>
<entry>AudioVideo</entry>
</row><row>
<entry>Midi</entry>
<entry>An app related to MIDI</entry>
<entry>Audio</entry>
</row><row>
<entry>Mixer</entry>
<entry>Just a mixer</entry>
<entry>Audio</entry>
</row><row>
<entry>Sequencer</entry>
<entry>A sequencer</entry>
<entry>Audio</entry>
</row><row>
<entry>Tuner</entry>
<entry>A tuner</entry>
<entry>Audio</entry>
</row><row>
<entry>Video</entry>
<entry>A video application</entry>
<entry>AudioVideo</entry>
</row><row>
<entry>TV</entry>
<entry>A TV application</entry>
<entry>Video</entry>
</row><row>
<entry>AudioVideoEditing</entry>
<entry>Application to edit audio/video files</entry>
<entry>Audio or Video or AudioVideo</entry>
</row><row>
<entry>Player</entry>
<entry>Application to play audio/video files</entry>
<entry>Audio or Video or AudioVideo</entry>
</row><row>
<entry>Recorder</entry>
<entry>Application to record audio/video files</entry>
<entry>Audio or Video or AudioVideo</entry>
</row><row>
<entry>DiscBurning</entry>
<entry>Application to burn a disc</entry>
<entry>AudioVideo</entry>
</row><row>
<entry>Game</entry>
<entry>A game</entry>
</row><row>
<entry>ActionGame</entry>
<entry>An action game</entry>
<entry>Game</entry>
</row><row>
<entry>AdventureGame</entry>
<entry>Adventure style game</entry>
<entry>Game</entry>
</row><row>
<entry>ArcadeGame</entry>
<entry>Arcade style game</entry>
<entry>Game</entry>
</row><row>
<entry>BoardGame</entry>
<entry>A board game</entry>
<entry>Game</entry>
</row><row>
<entry>BlocksGame</entry>
<entry>Falling blocks game</entry>
<entry>Game</entry>
</row><row>
<entry>CardGame</entry>
<entry>A card game</entry>
<entry>Game</entry>
</row><row>
<entry>KidsGame</entry>
<entry>A game for kids</entry>
<entry>Game</entry>
</row><row>
<entry>LogicGame</entry>
<entry>Logic games like puzzles, etc</entry>
<entry>Game</entry>
</row><row>
<entry>RolePlaying</entry>
<entry>A role playing game</entry>
<entry>Game</entry>
</row><row>
<entry>Simulation</entry>
<entry>A simulation game</entry>
<entry>Game</entry>
</row><row>
<entry>SportsGame</entry>
<entry>A sports game</entry>
<entry>Game</entry>
</row><row>
<entry>StrategyGame</entry>
<entry>A strategy game</entry>
<entry>Game</entry>
</row><row>
<entry>Education</entry>
<entry>Educational software</entry>
</row><row>
<entry>Art</entry>
<entry>Software to teach arts</entry>
<entry>Education</entry>
</row><row>
<entry>Construction</entry>
<entry></entry>
<entry>Education</entry>
</row><row>
<entry>Music</entry>
<entry>Musical software</entry>
<entry>AudioVideo;Education</entry>
</row><row>
<entry>Languages</entry>
<entry>Software to learn foreign languages</entry>
<entry>Education</entry>
</row><row>
<entry>Science</entry>
<entry>Scientific software</entry>
<entry>Education</entry>
</row><row>
<entry>Astronomy</entry>
<entry>Astronomy software</entry>
<entry>Science</entry>
</row><row>
<entry>Biology</entry>
<entry>Biology software</entry>
<entry>Science</entry>
</row><row>
<entry>Chemistry</entry>
<entry>Chemistry software</entry>
<entry>Science</entry>
</row><row>
<entry>Geology</entry>
<entry>Geology software</entry>
<entry>Science</entry>
</row><row>
<entry>Math</entry>
<entry>Math software</entry>
<entry>Science</entry>
</row><row>
<entry>MedicalSoftware</entry>
<entry>Medical software</entry>
<entry>Science</entry>
</row><row>
<entry>Physics</entry>
<entry>Physics software</entry>
<entry>Science</entry>
</row><row>
<entry>Teaching</entry>
<entry>An education program for teachers</entry>
<entry>Education</entry>
</row><row>
<entry>Amusement</entry>
<entry>A simple amusement</entry>
<entry></entry>
</row><row>
<entry>Applet</entry>
<entry>An applet that will run inside a panel or another such application, likely desktop specific</entry>
<entry></entry>
</row><row>
<entry>Archiving</entry>
<entry>A tool to archive/backup data</entry>
<entry></entry>
</row><row>
<entry>Electronics</entry>
<entry>Electronics software, e.g. a circuit designer</entry>
<entry></entry>
</row><row>
<entry>Emulator</entry>
<entry>Emulator of another platform, such as a DOS emulator</entry>
<entry></entry>
</row><row>
<entry>Engineering</entry>
<entry>Engineering software, e.g. CAD programs</entry>
<entry></entry>
</row><row>
<entry>FileManager</entry>
<entry>A file manager</entry>
<entry></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><row>
<entry>Screensaver</entry>
<entry>A screen saver (launching this desktop entry should activate the screen saver)</entry>
<entry></entry>
</row><row>
<entry>TerminalEmulator</entry>
<entry>A terminal emulator application</entry>
<entry></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>
<entry></entry>
</row><row>
<entry>System</entry>
<entry>System application, "System Tools" such as say a log viewer or network monitor</entry>
<entry>(Settings)</entry>
</row><row>
<entry>Filesystem</entry>
<entry>A file system tool</entry>
<entry>System</entry>
</row><row>
<entry>Monitor</entry>
<entry>Monitor application/applet that monitors some resource or activity</entry>
<entry>System</entry>
</row><row>
<entry>Security</entry>
<entry>A security tool</entry>
<entry>Settings or System</entry>
</row><row>
<entry>Utility</entry>
<entry>Small utility application, "Accessories"</entry>
<entry></entry>
</row><row>
<entry>Accessibility</entry>
<entry>Accessibility</entry>
<entry>Settings or Utility</entry>
</row><row>
<entry>Calculator</entry>
<entry>A calculator</entry>
<entry>Utility</entry>
</row><row>
<entry>Clock</entry>
<entry>A clock application/applet</entry>
<entry>Utility</entry>
</row><row>
<entry>TextEditor</entry>
<entry>A text editor</entry>
<entry>Utility</entry>
</row><row>
<entry>KDE</entry>
<entry>Application based on KDE libraries</entry>
<entry>QT</entry>
</row><row>
<entry>GNOME</entry>
<entry>Application based on GNOME libraries</entry>
<entry>GTK</entry>
</row><row>
<entry>GTK</entry>
<entry>Application based on GTK+ libraries</entry>
<entry></entry>
</row><row>
<entry>Qt</entry>
<entry>Application based on Qt libraries</entry>
<entry></entry>
</row><row>
<entry>Motif</entry>
<entry>Application based on Motif libraries</entry>
<entry></entry>
</row><row>
<entry>Java</entry>
<entry>Application based on Java GUI libraries, such as AWT or Swing</entry>
<entry></entry>
</row><row>
<entry>ConsoleOnly</entry>
<entry>Application that only works inside a terminal (text-based or command line application)</entry>
<entry></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
system wide 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-desktop-file-id"><glossterm>Desktop-File Id</glossterm>
<glossdef>
<para>
The id to identify a desktop entry with.
For example, if <filename>/usr/share/applications</filename> is
specified as an <AppDir>, and <filename>/opt/ude</filename>
as <LegacyDir prefix="foo-">
then
<filename>/usr/share/applications/foo/bar.desktop</filename>,
<filename>/usr/share/applications/foo-bar.desktop</filename>
and
<filename>/opt/ude/Settings/bar.desktop</filename> all have
the same desktop-file id <literal>foo-bar.desktop</literal>
</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 directory entry, relative to the
<DirectoryDir> containing the
entry. For example, if <filename>/usr/share/desktop-directories</filename> is
specified as an <DirectoryDir>, the relative path to
<filename>/usr/share/desktop-directories/foo/bar.directory</filename> is
<filename>foo/bar.directory</filename>.
</para>
</glossdef>
</glossentry>
</glossary>
</article>
|