which are typically primitive widgets that act as tab group members. Furthermore, manager widgets must handle all of
the input events for gadgets, so there is a great deal of functionality that supports keyboard traversal written into the
Manager widget class.
Before we discuss the details of dealing with tab groups, there are a few things we should mention. The
implementation of tab groups has changed from earlier versions of the toolkit; to maintain backwards compatibility,
remnants of the older implementation are still resident in the current implementation, which may cause some
confusion in the current API. The technology of keyboard traversal is still being improved. Although later
implementations may not change the existing API, new versions of the toolkit may optimize the process substantially.
Since the current implementation of tab groups is not perfect, some people want to change the default behavior and
control it entirely on their own. We do not recommend this approach. You should avoid interfering with the keyboard
traversal mechanisms, as it will make it easier to maintain compatibility with other Motif applications and it won't
require any changes for new versions of the toolkit. If you are going to modify the operation of keyboard traversal,
you should be careful and test your changes thoroughly.
9.8.1 Turning Traversal Off
You can prevent a widget from participating in keyboard traversal by removing the widget from the traversal list. To
remove a widget from the traversal list, set its XmNtraversalOn resource to False. If the widget is a member of a
tab group, it is simply removed from the list and the user cannot traverse to it. If the widget is a tab group, it is
removed and all of its elements are also all removed.
Let's experiment with tab group members by modifying tictactoe.c. We can modify the pushed() callback routine
to remove the selected PushButton from the traversal list when it is selected. If the keyboard is used to traverse and
select the items on the tic−tac−toe board, the toolkit automatically skips over those that have already been selected.
The new callback routine is shown in the source code XtSetLanguageProc() is only available in X11R5; there is
no corresponding function in X11R4.
void
pushed(w, client_data, call_data)
Widget w;
XtPointer client_data;
XtPointer call_data;
{
char buf[2];
XmString str;
int letter;
XmPushButtonCallbackStruct *cbs =
(XmPushButtonCallbackStruct *) call_data;
XtVaGetValues (w, XmNuserData, &letter, NULL);
if (letter) {
XBell (XtDisplayOfObject (w), 50);
return;
}
/* Shift key gets an O. (xbutton and xkey happen to be similar) */
if (cbs−>event−>xbutton.state & ShiftMask)
letter = buf[0] = '0';
else
letter = buf[0] = 'X';
buf[1] = 0;
str = XmStringCreateLocalized (buf);
XtVaSetValues (w,
XmNlabelString, str,
XmNuserData, letter,
9 Manager Widgets 9.8.1 Turning Traversal Off
244
XmNshadowThickness, 0,
XmNtraversalOn, False,
NULL);
XmStringFree (str);
}
The user can still click on a previously−selected item with the mouse button, but the routine causes an error bell to
sound in this situation.
Output−only widgets, like Labels and Separators, always have their XmNtraversalOn resource initialized to
False. In most cases, setting the value to True would be annoying to the user, since these objects cannot respond to
keyboard input anyway. The user would have to traverse many unimportant widgets to get to a desired item. However,
it is commonly overlooked that a Label can have a XmNhelpCallback routine associated with it. If the keyboard
traversal mechanism allows the user to traverse to Labels, he could get help on them by pressing the HELP or F1 keys.
It may be considered a design flaw in Motif that a non−mouse−driven interface is not supported for getting help for
these objects. However, this situation is not generally a problem, since most people do not try to get help on Labels
and most programmers do not install help for them.
A general problem that people tend to have with the PanedWindow widget is that the Sashes are included in the
traversal list. Since the PanedWindow is a manager widget, it is a tab group, which means that all of its children are
members of the tab group. If you run the program from the source code and use the TAB key to move from one
widget to the next, you'll find that the traversal also includes the Sash widgets. Many users find it annoying to traverse
to Sashes, since it is more likely that they want to skip the Sashes when using keyboard traversal, rather than use them
to resize any of the panes. While it is common to resize panes, people usually do so using the mouse, not the
keyboard.
As of Motif 1.2, it is possible to turn off Sash traversal using the following resource specification in a resource file:
*XmSash.traversalOn: False
Prior to this release, the PanedWindow and its Sashes were created in such a way that you could not override the
traversability of the Sashes using hard−coded values in the widget creation call or using a resource specification in a
resource file. In fact, the internals of the PanedWindow widget hard−coded its Sash widgets' XmNtraversalOn
resources to True as they were created, thus eliminating the possibility of turning traversal off using resources. The
only way to turn off traversal for Sashes in this case was to reset the resource values after all of the Sashes were
created. the source code demonstrates a routine that handles this task.
#include <Xm/SashP.h>
void
TurnOffSashTraversal (panedw)
Widget panedw;
{
Widget *children;
int num_children;
XtVaGetValues (panedw,
XmNchildren, &children,
XmNnumChildren, &num_children,
NULL);
while (num_children−− > 0)
if (XmIsSash (children[num_children]))
XtVaSetValues (children[num_children],
XmNtraversalOn, False,
NULL);
9 Manager Widgets 9.8.1 Turning Traversal Off
245

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.