XPMENU Cross Platform Menus

Table of Contents

  1. Overview (introduction, general goals, etc)
  2. XUL Elements (brief description of associated XUL elements)
  3. Meeting Menu Requirements (comparisons with <menu>)
  4. Extending Menu Requirements (enhanced features, example)
  5. Full Element Reference (proposed XUL elements, special features)
  6. CSS Implemenation (Specific CSS stuff)
  7. Actual Implementation (description of basic menuitems)
  8. Special Quirks (related to MSOffice, MSIE menus)
  9. Difficulties (MacOS discrepancies, suggestions for dealing with them)
  10. Related Links
  11. Note from Author & contact information.


This document is a description of the Cross Platform Menu <xpmenu> element. It is derived from the description of the <menu> element written by Chris Saari, which can be found here: http://www.mozilla.org/xpfe/MenuRequirements.html

xpmenu is a XUL element that specifies a platform independent application menu system. The idea is that rather than relying on platform specific menu code, it'd be quicker, easier, and just plain fun to do an XP version, as Mozilla has already done with other graphics widgets (like checkmarks, radio buttons, et al.)

General Goal: create a highly extensible menu system that works independent of platform.

The xpmenu (and its related elements) are similar but not identical to <menu>. This is because when dealing with standard platform menus, there is little control over the actual appearance of the menu. (unless you're Microsoft and can make crazy expanding and collapsing menus) With the current <menu> system, you're limited to basically setting elements, submenus, keyboard accelerators, checkmarks, and separators. Cool late '90s fads like little icons in the menus and drag and drop customizability are not easily possible, and as such are not in the original specification.

xpmenus, on the other hand, being rendered by the layout engine, offer complete flexibility - all the attributes that can be set using CSS to a box can be applied to an xpmenu. The enhancements this offers will be discussed in this document.

xpmenus also have some limitations, which are documented as well, towards the end.


xpmenus have been landed. There are still some bugs at time of writing, but these are being worked on. With the landing, the xpmenu element has been replaced by <menu> (that is, old <menu> tags now display the new menu system rather than the old). Note that all the references to elements in this document now have a superfluous "xp" on the start, which should be removed in actual XUL code to make your menus function properly. I have left this document with the xps in to help differentiate between the new system and the old, and because I'm lazy.


XUL Elements

xpmenus are contained in xpmenubars, and consist of xpmenuitems, which are xpmenuchildren of the xpmenus. But of course that should have been xpmenuobvious.

A box thing that contains a collection of menus. Its analogous to a <menubar>, but is rendered inside a toolbox, just like a toolbar.

This is the equivalent of a <menu>. Basically it's a container that contains some <xpmenuchildren> (see below). Imagine the "File" menu, or the "Edit" menu, and you have a menu in the sense that an <xpmenu> is a menu. Blargh.

These are the elements housed inside the menu popup created by an <xpmenu>. This is one of the differences from the standard <menu> implementation, and is necessary because since <xpmenu>s are rendered by the layout engine not the OS, we need to specify a menu look to them (give them a 3D edge, use outlines etc). Note: This element was originally in place as a hack and called <xpmenuchildren>. Eventually, there are plans to allow you to define the style of the popup itself (since that's all the xpmenuchildren element controls) through use of a pseudoelement of xpmenu:

  // Define the border and background image for the popup menu

When this happens, the xpmenu element will be removed. Bear this in mind when developing xpmenu systems using the current builds (this document will be updated to reflect any future changes in this regard).

An item in the menu. It has several advantages. I'll get to those later, though.

In this context, a <menuseparator /> is a HTML horizontal rule with 3D shading, because they look the same as menu separators.

Meeting the Requirements of the Menu Element

Chris Saari's <menu> document required menus to have certain capabilities - such as support for, keyboard navigation, etc. David Hyatt has already done some of this (keyboard navigation etc), and is continuing to do so in his spare time. An example that you can test is res/samples/xpmenu.xul - load it in apprunner or viewer to see it in action!

As for streaming, I'd expect this functionality to be as simple to implement using NGLayout rendered content as with OS generated menus, if not simpler.

RDF capability is a non-issue, other XUL elements such as toolbars and trees can already draw their content from RDF specification.

Extending the Features of the Menu Element

It has been asked on the various Mozilla development newsgroups if Mozilla would support icons in menus. The first answer was no. With menus that are rendered by the layout engine, the answer is an emphatic yes!

Actually, icons are only the beginning. Menu items and menus will be boxes that take a number of parameters as attributes, which you can set to define a standard menu. E.g.:

 <xpmenu value="<html:u>F</html:u>ile" accesskey="f">
   <xpmenuitem value="<html:u>N</html:u>ew" id="fileNew accesskey="n"/>


This creates a menu bar, with a single menu element called "File". In this case, the letter F is underlined, and the key mapping for Alt-key use is set to "f" using the HTML4.0 accesskey attribute.

Note that I've captioned the elements with "value" instead of "name", to make it more consistent with other layout rendered frames, like titledbuttons. Besides, name is too easily confused with "ID" IMO.

The xpmenu contains a xpmenupopup wrapper which holds the contents of the popup created when the user selects that menu item. The style of this will be set in the XUL appearance description file (xul.css). If you don't like this standard formatting, you can derive your own. You can make the menus transparent, and make their contents blink.

In this simple example, we have one xpmenuitem with its value set in a similar way to xpmenu, and a keyboard shortcut key. Keyboard accelerators are set using the keymapping XUL element, so the only purpose of the accelkey attribute is to tell the layout engine what the associated mapping is so it can display it.

There is the familiar id attribute that points to a CSS specification for the element. The image displayed to the left of the caption is set using the list-style-image CSS property, as is the case with titledbutton.

These are just a few attributes. The rest will be explained below.

Since the xpmenuitems and xpmenus are just frames, you can also fill them with arbitrary content, and create whatever style of menu you wish, if you find the standard type too boring. If you want to put in flash animations, mpegs, or gigantic jpegs of your girlfriend, xpmenu makes this possible. (as with the rest of the XPFE, the power awarded comes with resposibility ;)

Full Reference

Here's my recommendation for a full implementation of a xpmenu system. Whether or not it turns out like this is entirely up to the people with the skills to actually write C++.. When writing this, I tried to achieve parity with other widgets, so attributes familiar with other widgets and conventions when dealing with them would be used here as well.

<xpmenubar> element
A basic box element that resides in a toolbox.

chromeclass set this to "menubar"

<xpmenu> element
A container element that holds one or more xpmenuitems, displayed in the xpmenubar as a string representing the name of the menu, or in a menu popup as a regular menu item, but with some characteristics indicating that it spawns a popup submenu.

value the caption of the menu. Can contain HTML to format the string, e.g. to underline the accesskey.
accesskey the key used to provide Alt access to the element, either by holding down alt and hitting that key, or by pushing Alt to activate the menu bar, and then selecting a key on the keyboard.
disabled this is a boolean property that toggles the availability of the item. You can create a separate CSS definition for this, and create a separate disabled image (with list-style-image)

Notes If this item is contained inside a menu popup (i.e. if it refers to a submenu) then an arrow indicator is placed to the right of the caption to indicate cascading submenu, as is used in the various platforms. This does not appear if the xpmenu is toplevel - i.e. you don't see the arrow next to the caption of the menu on the xpmenubar. That would look silly.

If you don't think that would look silly, or you have some other idea of how menus should work, note that the default attributes xpmenu are provided for mere convenience, and you are free to ignore all of them, and define your own style, as xpmenus are mere frame containers:

 <html:blink>File</html:blink><html:img src="arrows_on_top_level_xpmenus_are_not_silly.gif"/>
  ...the rest of your menu...

<xpmenuitem> element
A container element that represents an item in the menu. As with xpmenu, it contains some convenience attributes that you can use to define a menu that looks fairly standard, or you can ignore them, and define something completely different.

value the caption of the menu. Can contain HTML to format the string, e.g. to underline the accesskey.
accesskey the key used to provide Alt access to the element, either by holding down alt and hitting that key, or by pushing Alt to activate the menu bar, and then selecting a key on the keyboard.
key a pointer to the id of a XUL key element that represents the keyboard accelerator for the menuitem. the value of the keystroke (e.g. Ctrl+N) is read from this element and displayed.
acceltext a string representing the accelerator key combination that activates the function called by this menu, where a nonstandard key combination like DEL, or a function key is to be displayed. Otherwise, use the key property to connect a menu to a key element. This has no significance in keymapping, as this is done through keyset/key elements (see key property). The purpose here is to provide a graphical display of what keys correspond to what menu items, and nothing more. What I would suggest is that this string, like the value string, be stored as an entity in the DTD, so that it can be localised. (for instance, Ctrl+N for new window means nothing to someone whose native language is pig latin, where new would be "ewnay", and the most obvious keystroke in that case would be Ctrl+E).
type analogous to the form input tag attribute. This can be set to either check, radio, or button. The default is button, so if this attribute is omitted, the menuitem is treated as a normal item. If it is set to check, the menu item has a checkmark drawn to the left of the caption, unless an image src is provided to override the checkmark image (which would be provided with the chrome). If radio is specified, the menuitem is part of a radio group, which is defined by the name attribute. I'm not sure if anyone uses this feature, but some applications have form text fields in their menus, but this is probably getting a little complex for the default attributes. (you can do this by making a custom menu item)
name an attribute useful for defining radio groups. Each item in the radio group must have a different ID, but the same name to specify the group, just like in HTML.
checked analagous to HTML forms
disabled this is a boolean property that toggles the availability of the item. You can create a separate CSS definition for this, and create a separate disabled image (with list-style-image)

Again, if these default attributes fall short of what you want, feel free to ignore them and use <xpmenuitem> to contain whatever item content you want.

<xpmenupopup> element
xpmenupopup exists as a container for elements in a menu popup. It requires no specialist formatting attributes as these can all be set from CSS (e.g. borders, outlines, background colors etc). (See comments above about the future of xpchildren in Mozilla)

Event Handling
Menus will support oncreate and ondestroy events. In earliest implementations, one had to use onclick to map an event to a menu selection. However this has been changed to onaction. This may change further to onexecute or oncommand, or something similar.


CSS Implementation

Also required is some use of CSS tweaks.

The xpmenus must support checkmarking and radio button use. The software will provide default checkmarks and radio button images that will sit in the same place as the images. If you don't like these, you can override them by supplying a src attribute to the <xpmenuitem> tag.

I'm guessing you could set the checked and unchecked images yourself using something like this:

To specify a checked image: xpmenuitem[type=check]:-moz-checked (or whatever is used, I'm not sure)

and a plain image: xpmenuitem[type=check]

you set the image using the list-style-image property, as with titledbuttons.

Actual Implementation

Assuming you elect to use the default attributes, an xpmenuitem will assume this form:


and a xpmenu inside a menu popup will be the same, except the space occupied by accelkey will be used by the little arrow signifying the submenu.

If you use <xpmenuitem> and <xpmenu> as containers for your own menuing system, you can do whatever you want.

Keyboard Navigation

Fluid keyboard navigation, in my mind, is essential to any good menu navigation system. The xpmenu system offers comprehensive keyboard navigation support. Here's how it will work:

Arrow keys - navigation (left and right, up and down)
ALT - by itself activates/deactivates the menu
ESC - closes up one level of menu
ALT+key combo - access keys
HOME - selects the first item in a menu
END - selects the last item in a menu
ENTER - opens a menu item or invokes a menu



So far, what we have here would be a kick-ass menu system if it weren't for one thorn in our proverbial side: MacOS. General MacOS UI guidelines dictate that an application menu must go at the top of the screen, unlike Windows and X software, where the menubar belongs to the application window. Our cunning plan of creating menubars that look like toolbars comes to a grinding halt here, unless we can:

Create a hack that parses the xpmenu structure, and adds menus to the menu bar based on information supplied in the attributes to <xpmenu> and <xpmenuitem>. There are two ways to do this, the easy way is to create a standard Mac menu bar with standard menu popups that are created by getting the value attributes from all the xpmenu elements and stripping the HTML, and adding them, and other relevant bits of information, The hard way is to create a standard mac menubar, but have menu popups that are rendered by the layout engine, that just happen to appear on the screen where one would expect a regular menu item to pop up. I'd imagine this would be a lot harder, but its the way to extend the most functionality.

Notice that this whole "hack" thing ruins half the idea of having XP menus in the first place - they're no longer completely XP. Nevertheless, I suppose we can't avoid some level of OS specific code, the original plan is to deliver a product using OS menus on the different platforms, so a hack is still an improvement! I'll leave this one for discussion on the appropriate newgroups.

I asked Dave Hyatt, and he offered this partial solution:

"Note that with the xpmenuchildren tag eliminated, the syntax becomes interoperable with the macintosh menus and we could just use the same tags. This would be cool. My thinking is that if you just say and didn't specify the menu contents that I would make the default contents (e.g., I'd create File in a box etc. etc. The Mac would just build the menu item out of the attributes on the menuitem node However if the user puts content in there on his own other than child menus or menu items, I'll use that as the menu's content instead. "

Related Links

Note from the Author

This article, like most XPFE documentation, is probably incomplete. If you notice any glaring omissions, or have any comments, flames or suggestions, please send feedback. See below for contact details.

Contact Details

24/07/99, 03/08/99 Ben Goodger