A PopupMenu is normally invisible. When the user takes some action--usually pressing Btn3 or osfMenu--in a widget that has a PopupMenu, the menu is posted. The user moves from item to item in the menu by dragging Btn3 or, when keyboard traversal is enabled, by keyboard traversal actions. Motif unposts the menu when the user activates an item in the menu system (other than a CascadeButton), presses osfCancel, or releases or clicks Btn3 outside a menu item.
A PopupMenu RowColumn must have a MenuShell parent. The parent of the MenuShell is the widget with which the PopupMenu is associated. Because the MenuShell is a popup child of its parent, the parent can be any widget (but not a gadget); it does not have to be a subclass of Composite. The Motif convenience routines that create PopupMenus automatically create a MenuShell as the parent of the PopupMenu RowColumn.
Several different widgets may share a given Popup menu. One widget must serve as the parent of the MenuShell, but other widgets may be nominated with the XmAddToPostFromList(3) function.
The PopupMenu's XmNmenuPost resource specifies the button event that posts the menu. This event will make the menu visible in any widget on the menu's list of eligible widgets. The event must be a button press, possibly with modifiers. However, you should not set XmNmenuPost to BTransfer Press because many button widgets use BTransfer Press as a default binding to initiate a Drag operation.
When a user creates a PopupMenu, Motif installs an event handler on the menu's widget parent. Called PopupMenuEventHandler, this routine performs most of the necessary setup for a PopupMenu, and manages the RowColumn widget as well.
On receipt of an event that should post a PopupMenu, this event handler searches the widget hierarchy and the popup list for the appropriate menu to post. The appropriate menu will have its XmNmenuPost resource match the triggering event, will have its XmNpopupEnabled resource set to XmPOPUP_AUTOMATIC or XmPOPUP_AUTOMATIC_RECURSIVE, and will have been created before any other PopupMenu that satisfies the same criteria. If the popup menu is found in a parent of the target widget, the XmNpopupEnabled resource must be set to XmPOPUP_AUTOMATIC_RECURSIVE.
Note: | In older versions of Motif, developers were required to write their own event handlers in order to implement PopupMenus. In the upgrade to version 2.0, substantial changes were made to the popup menu system to simplify the creation and management of PopupMenus. However, applications using this approach will still work correctly under the current version of Motif. |
Once a menu selection has been made, control shifts to the popupHandlerCallback procedure in the menu's parent widget, if there is one. The callback allows a more specific menu to be posted, if necessary, or can even perform the selected menu function, if desired.
A pointer to the following structure is passed to each callback for XmNpopupHandlerCallback:
typedef struct { int reason; XEvent * xevent; Widget menuToPost; Boolean postIt; Widget target; } XmPopupHandlerCallbackStruct;
Posting a PopupMenu through the keyboard is controlled by the PopupMenu's XmNmenuAccelerator and XmNpopupEnabled resources. XmNmenuAccelerator specifies a key event that may post the menu. XmNpopupEnabled specifies whether or not this event actually posts the menu. It also determines whether or not accelerators and mnemonics in the PopupMenu and its submenus are enabled.
An application can have only one active PopupMenu at a time for a particular widget. If the widget has more than one PopupMenu, the application should set XmNpopupEnabled to True for the active menu and set XmNpopupEnabled to False for all inactive menus.