This article is from the FAQ, by with numerous contributions by
X02) Why do I get the error "There must be only one non-shell widget which is son of Toplevel"?
Consider the following program:
--- program: descriptor ---
(# faculty: label
(# init:: (# do 2-> borderwidth #) #);
(# Physics, Mathematics: @faculty;
init:: (# do Physics.init; Mathematics.init #);
The idea was that a window with two labels named Physics and Mathematics
should appear. But executing it gives the error message
Xt Error: There must be only one non-shell widget which is son of
Toplevel. The widget causing the conflict is named faculty.
This is because the program uses the init pattern of the widgets without
specifying the father and name of the widgets. In the Xt manual [MIA 91-16],
it is briefly explained that the father widget will default to "the
enclosing widget according to BETA's scope rules" (see the description of
Core in "Basic XtEnv patterns").
To be precise, this is what happens: When the init pattern of a widget is
invoked, it first checked to see if the father is NONE. This will be the
case if no father is specified in the enter part of init. If so, a search is
started in the statical environment of the widget pattern. If a
specialization of a Core widget is found, this widget is used as the father.
This search is continued until a pattern with no enclosing pattern is found.
In this case the widget named TopLevel (in xtenv) is used as the father. The
widget TopLevel is an instance of the pattern TopLevelShell, which among its
characteristics has the constraint that it wants to have exactly one
Now consider the example program: The first thing that happens is that the
init attribute of University is invoked. Since no father is specified, a
search for one is started from the University pattern. This search finds the
pattern AwEnv(# ... #), which is not a Core, and which has no enclosing
pattern. Thus University will get the father widget TopLevel.
The final binding of University.init then invokes Physics.init. Physics is
an instance of the pattern faculty, which is declared in the same scope as
University. Thus the search for a father for Physics is identical to the
search for the father of University, and Physics also gets TopLevel as its
father. This is when the error occurs. The reason why the name reported in
the error message is faculty is explained in Question X01.
Notice that it did not matter that the instantiation of the Physics object
is done within University: the default father is searched for starting from
the pattern declaration of the object.
In general there are three possible solutions:
1. Supply the father and name when initializing the faculty widgets:
do ("Physics", University)->Physics.init;
In this case, no search for a default father is needed for the faculty
2. Make (possibly empty) specializations of faculty inside University:
Now the search for a default father of Physics will start at the
pattern faculty(##) inside University, so the University pattern will
be the first found in this search, and hence the University widget will
become the father of the Physics widget. Likewise for Mathematics.
3. Move the declaration of the faculty pattern inside the University
pattern. This will give the same search path as in solution 2.
(Conceptually, this might also be the best place to declare faculty in
the first place.)
The above example was a simple one. In more complicated cases, the reason
for an error of this kind can be trickier to spot. If your program uses the
fragment system to move declarations of useful widgets into a library, this
kind of error is likely to occur. Remember that if an instance of an
unspecialized widget is used, the widget pattern being declared in, say, the
XtEnvLib attributes slot of xtenv, then the search for a default father is
started at the XtEnv pattern, and therefore no father widget is found. In
this case the widget will get TopLevel as father. Solutions 1 or 2 above
will be appropriate in these cases.
See the X Windows Libraries Manual p5-7 for more details.