that invoke a menu item even when the menu is not displayed. Accelerators typically use the CTRL or ALT key to
distinguish them from ordinary keystrokes that are sent to the application. For example, again in the figure, the
Ctrl+C accelerator allows the user to exit the application without accessing the menu.
Before we plunge into the details of menu creation, a word of warning to experienced X Toolkit programmers is in
order. Motif does not use Xt's normal methods for creating and managing menus. In fact, you cannot use the standard
Xt methods for menu creation or management without virtually reimplementing the Motif menu design. If you need to
port an Athena or OPEN LOOK−based application to Motif, you will probably have to reimplement your menu
design. In Xt, you would typically create an OverrideShell that contains a generic manager widget, followed by a set
of PushButtons. To display the menu, you would pop up the shell using XtPopup(). The Motif toolkit abstracts the
menu creation and management process using routines that make the shell opaque to the programmer.
16.2 Creating Simple Menus
In Chapter 4, The Main Window, we used the simple menu creation routines to build the MenuBar and its associated
PulldownMenus. These routines are designed to be plug−and−play convenience routines; their only requirements are
compound strings for the menu labels and a single callback function that is invoked when the user activates any of the
menu items.
XmVaCreateSimpleMenuBar() creates a MenuBar, while XmVaCreateSimplePulldownMenu()
generates a PulldownMenu and its associated items. These functions take a variable−length argument list of
parameters that specify either the CascadeButtons for the MenuBar or the menu items for the PulldownMenu. You can
also pass RowColumn−specific resource/value pairs to configure the RowColumn widget that manages the items in
the menu. The functions are front ends for more primitive routines that actually create the underlying widgets, so they
are convenient for many simple menu creation needs. You should review Chapter 4, The Main Window, for more
information on how to use these functions.
Motif also provides simple creation routines for creating PopupMenus and OptionMenus. Both
XmVaCreateSimplePopupMenu() and XmVaCreateSimpleOptionMenu() are very similar to the routines
for creating PulldownMenus, so much of the information in Chapter 4 also applies to these functions.
16.2.1 Popup Menus
The only difference between XmVaCreateSimplePulldownMenu() and
XmVa-CreateSimplePopupMenu() is that the latter routine does not have a button parameter for specifying
the CascadeButton used to display the menu. Since PopupMenus are not associated with CascadeButtons, this
parameter isn't necessary. the source code demonstrates the creation of a simple PopupMenu.
XtSetLanguageProc() is only available in X11R5; there is no corresponding function in X11R4.
XmStringCreateLocalized() is only available in Motif 1.2; XmStringCreateSimple() is the
corresponding function in Motif 1.1.
/* simple_popup.c −− demonstrate how to use a simple popup menu.
* Create a main window that contains a DrawingArea widget, which
* displays a popup menu when the user presses the third mouse button.
*/
#include <Xm/RowColumn.h>
#include <Xm/MainW.h>
#include <Xm/DrawingA.h>
main(argc, argv)
int argc;
char *argv[];
16 Menus 16.2 Creating Simple Menus
434
{
XmString line, square, circle, exit, exit_acc;
Widget toplevel, main_w, drawing_a, popup_menu;
void popup_cb(), input();
XtAppContext app;
XtSetLanguageProc (NULL, NULL, NULL);
toplevel = XtVaAppInitialize (&app, "Demos", NULL, 0,
&argc, argv, NULL, NULL);
/* Create a MainWindow widget that contains a DrawingArea in
* its work window.
*/
main_w = XtVaCreateManagedWidget ("main_w",
xmMainWindowWidgetClass, toplevel,
XmNscrollingPolicy, XmAUTOMATIC,
NULL);
/* Create a DrawingArea −− no actual drawing will be done. */
drawing_a = XtVaCreateManagedWidget ("drawing_a",
xmDrawingAreaWidgetClass, main_w,
XmNwidth, 500,
XmNheight, 500,
NULL);
line = XmStringCreateLocalized ("Line");
square = XmStringCreateLocalized ("Square");
circle = XmStringCreateLocalized ("Circle");
exit = XmStringCreateLocalized ("Exit");
exit_acc = XmStringCreateLocalized ("Ctrl+C");
popup_menu = XmVaCreateSimplePopupMenu (drawing_a, "popup", popup_cb,
XmVaPUSHBUTTON, line, 'L', NULL, NULL,
XmVaPUSHBUTTON, square, 'S', NULL, NULL,
XmVaPUSHBUTTON, circle, 'C', NULL, NULL,
XmVaSEPARATOR,
XmVaPUSHBUTTON, exit, 'x', "Ctrl<Key>c", exit_acc,
NULL);
XmStringFree (line);
XmStringFree (square);
XmStringFree (circle);
XmStringFree (exit);
XmStringFree (exit_acc);
/* after popup menu is created, add callback for all input events */
XtAddCallback (drawing_a, XmNinputCallback, input, popup_menu);
XtRealizeWidget (toplevel);
XtAppMainLoop (app);
}
/* input() −− called in responses to events in the DrawingArea;
* button−3 pops up menu.
*/
void
input(widget, client_data, call_data)
Widget widget;
XtPointer client_data;
XtPointer call_data;
{
Widget popup = (Widget) client_data;
XmDrawingAreaCallbackStruct *cbs =
16 Menus 16.2 Creating Simple Menus
435
(XmDrawingAreaCallbackStruct *) call_data;
if (cbs−>event−>xany.type != ButtonPress ||
cbs−>event−>xbutton.button != 3)
return;
/* Position the menu where the event occurred */
XmMenuPosition (popup, (XButtonPressedEvent *) (cbs−>event));
XtManageChild (popup);
}
/* popup_cb() −− invoked when the user selects an item in the popup menu */
void
popup_cb(menu_item, client_data, call_data)
Widget menu_item;
XtPointer client_data;
XtPointer call_data;
{
int item_no = (int) client_data;
if (item_no == 3) /* Exit was selected −− exit */
exit (0);
puts (XtName (menu_item)); /* Otherwise, just print the selection */
}
This program creates a standard MainWindow widget that contains a DrawingArea widget. The program does not do
any drawing; it is just a skeleton that demonstrates how to attach a PopupMenu. The PopupMenu is created using
XmVaCreateSimplePopupMenu() with the DrawingArea widget as its parent. The menu is popped up when the
user presses the third mouse button in the DrawingArea, as shown in the figure.
Output of simple_popup.c
The Motif toolkit does not handle posting a PopupMenu automatically, as it does with PulldownMenus and
OptionMenus, so we must watch for the appropriate events ourselves. We use the XmNinputCallback resource of
the DrawingArea widget to monitor events, as the routine is called whenever a keyboard or mouse action happens in
the widget. In a real application, we would use this routine to handle drawing as well. However, in this case, the
input() routine only looks for ButtonPress events for the third mouse button. The menu is passed as the client
data to input().
If input() sees an appropriate event, it uses the XmMenuPosition() routine to position the menu at the
16 Menus 16.2 Creating Simple Menus
436
Get Volume 6A: Motif Programming Manual now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.