X11workbench Toolkit  1.0
Menu Resources and Menu Callbacks

For menus to be processed automatically by a Frame Window, you need to set up menu resources and callback function arrays.

The menu identifiers are atoms that are specified using plain text identifiers, both in the menu resource AND in the menu callback arrays. These callback arrays are assigned to both Frame Windows and Child Frames.

When a Child Frame has a menu assigned, or a menu callback array, whenever it is active its menu and/or callback array is used for automatic menu processing. Otherwise, the menu and/or callback array for the Frame Window will be used.

The Frame Window allows you to automatically specify a menu resource and menu callback array when you create it, via the FWCreateFrameWindow() function, and the FWSetMenuHandlers() function. You first create the window, and then assign its menu handlers whenever you need them. You can also assign different handlers for different application states, as necessary.

A typical menu resource might look like the following example:

static char szAppMenu[]="1\n"
"_New File\tIDM_FILE_NEW\tNew File\tCtrl+N\n"
"_Open File\tIDM_FILE_OPEN\tOpen File\tCtrl+O\n"
"E_xit\tIDM_FILE_EXIT\tClose Application\tAlt+F4\n"
"_Contents\tIDM_HELP_CONTENTS\tHelp Contents\tAlt+F1\n"
"Conte_xt\tIDM_HELP_CONTEXT\tContext Help\tF1\n"
"_About X11workbench\tIDM_HELP_ABOUT\tAbout X11workbench\tAlt+F1\n"
"_Options\tIDM_TOOLS_OPTIONS\tDisplay Options Editor\n"

This example shows top level menus for 'File', 'Tools', and 'Help' with a separator between 'Tools' and 'Help'. The '_' indicates that the next char will be displayed with an underscore, AND that it will act as a hotkey (top-level menus use Alt+char as the hotkey; popups can use other combinations).

To make the menu work, you need that callback array. For this menu, a simplified callback array is shown here (it uses macros for initialization):


The FW_MENU_HANDLER_BEGIN macro creates a variable 'main_menu_handlers' that is an array containing the menu handler information. Each entry following that has 3 parameters:

  • The string identifier, in quotes, as defined in the menu resource
  • The menu callack that is invoked when the menu item is selected. Can be NULL if only a UI callback is needed.
  • The (optional) 'UI' menu callback that is invoked when the menu needs information on how to display itself. if there is no UI callback, then specify NULL.

A menu UI callback returns a negative value to 'disable', or zero to 'enable' a menu item. Other capabilities are reserved for future use.


The menu resources themselves consist of a set of lines, with several tab-delimited parameters on each line. The types of menu entries are:

  • Menu Identifier: a number followed by a linefeed '\n'. This identifies a specific menu within the resource. The top level menu should be identfied with a "1\\n".
  • Menu Item: A string, followed by tabbed columns indicating the identifier, tooltip text, and shortcut key, and ending with a linefeed. Top level menu items will not have shortcut keys.
  • Popup Menu: A string, followed by tabbed columns, the first being the word 'popup', followed by a popup menu ID (a number), and a linefeed.
  • Separator: Begins with a tab character, and is followed by the word 'separator' and a linefeed.
  • Dynamic: (reserved) Begins with a tab character, followed by the word 'dynamic', a tab, and an identifier that will be passed to a UI callback. The UI callback will indicate which menu items will be inserted at that position. This functionality is reserved for future use.

Popups are each identified by their own resource, which begins with a single number followed by a linefeed, followed by additional menu resource information. In the example, there are 4 popup menus identified by the numbers '2' through '5'. These can invoke other popup menus, as needed.

Menu callback functions have prototypes similar to the following:

int MenuHandler(XClientMessageEvent *pEvent);

It will be invoked by passing in a Client Message event, where the Atom for 'pEvent->message_type' will be 'aMENU_COMMAND', and pEvent->data.l[0] will contain the menu item's Atom. This way, it is possible to share the same callback function for multiple message identifiers, by checking the contents of the XClientMessageEvent to determine how to process it.

A menu UI callback function is declared similar to the following:

int MenuUIHandler(WBMenu *pMenu, WBMenuItem *pMenuItem);

The 'pMenu' and 'pMenuItem' pointers identify the menu and menu item associated with the UI request. The function will return '1' to enable, or -1 to disable the menu item associated with the callback. A value of '0' is currently undefined, and will result in a behavior as if NO UI callback were defined.