Search the FAQ Archives

3 - A - B - C - D - E - F - G - H - I - J - K - L - M
N - O - P - Q - R - S - T - U - V - W - X - Y - Z
faqs.org - Internet FAQ Archives

comp.windows.x.intrinsics Frequently Asked Questions (FAQ)
Section - 4.! How do I use a different visual than the default?

( Single Page )
[ Usenet FAQs | Web FAQs | Documents | RFC Index | Zip codes ]


Top Document: comp.windows.x.intrinsics Frequently Asked Questions (FAQ)
Previous Document: 3. Why does my app core dump when I use signals/alarms/cthreads?
Next Document: 5. Which visual should an application use?
See reader questions & answers on this topic! - Help others by sharing your knowledge
----------------------------------------------------------------------

This requires a more complicated answer than it should.  A window has
three things that are visual specific -- the visual, colormap and
border pixmap.  All widgets have their own Colormap and BorderPixmap
resource; only shell widgets have Visual resources (another questions
deals with why shells have a Visual).  The default value of these
resources is CopyFromParent which does exactly what it says.  In the
shell widget CopyFromParent gets evalulated as DefaultVisualOfScreen
and DefaultColormapOfScreen.  When any one of the three resources is
not properly set, a BadMatch error occurs when the window is
created.  They are not properly set because each of the values depends
on the visual being used.  

How to get this to work?  There are two parts to the answer.  The
first is if you want an application to start with a particular visual
and the second is if you want a particular shell within an application
to start with a different visual.  The second is actually easier
because the basic information you need is available.  The first is a
little harder because you'll need to initialize much of the toolkit
yourself in order to determine the needed information.

/*
 * Some sample code to start up an application using something other
 * than the default visual.
 *
 * To compile:
 *	cc -g visual.c -o visual -lXaw -lXmu -lXt -lXext -lX11 -lm
 *
 * To run:
 *	./visual -geometry 300x300 -depth 24 -visual StaticColor -fg blue -bg yellow
 *
 * you need to move the mouse to get the particular visuals colormap
 * to install.
 */

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>

typedef struct
{
	Visual	*visual;
	int	depth;
} OptionsRec;

OptionsRec	Options;

XtResource resources[] =
{
	{"visual", "Visual", XtRVisual, sizeof (Visual *),
	XtOffsetOf (OptionsRec, visual), XtRImmediate, NULL},
	{"depth", "Depth", XtRInt, sizeof (int),
	XtOffsetOf (OptionsRec, depth), XtRImmediate, NULL},
};

XrmOptionDescRec Desc[] =
{
	{"-visual", "*visual", XrmoptionSepArg, NULL},
	{"-depth", "*depth", XrmoptionSepArg, NULL}
};



int
main (argc, argv)
	int		argc;
	char		**argv;
{
	XtAppContext	app;		/* the application context */
	Widget		top;		/* toplevel widget */
	Display		*dpy;		/* display */
	char		**xargv;	/* saved argument vector */
	int		xargc;		/* saved argument count */
	Colormap	colormap;	/* created colormap */
	XVisualInfo	vinfo;		/* template for find visual */
	XVisualInfo	*vinfo_list;	/* returned list of visuals */
	int		count;		/* number of matchs (only 1?) */
	Arg		args[10];
	Cardinal	cnt;
	char		*name = "test";
	char		*class = "Test";

	/*
	 * save the command line arguments
	 */

	xargc = argc;
	xargv = (char **) XtMalloc (argc * sizeof (char *));
	bcopy ((char *) argv, (char *) xargv, argc * sizeof (char *));

	/*
	 * The following creates a _dummy_ toplevel widget so we can
	 * retrieve the appropriate visual resource.
	 */
	cnt = 0;
	top = XtAppInitialize (&app, class, Desc, XtNumber (Desc), &argc, argv,
			       (String *) NULL, args, cnt);
	dpy = XtDisplay (top);
	cnt = 0;
	XtGetApplicationResources (top, &Options, resources,
				   XtNumber (resources),
				   args, cnt);
	cnt = 0;
	if (Options.visual && Options.visual != DefaultVisualOfScreen (XtScreen (top)))
	{
		XtSetArg (args[cnt], XtNvisual, Options.visual); ++cnt;
		/*
		 * Now we create an appropriate colormap.  We could
		 * use a default colormap based on the class of the
		 * visual; we could examine some property on the
		 * rootwindow to find the right colormap; we could
		 * do all sorts of things...
		 */
		colormap = XCreateColormap (dpy,
					    RootWindowOfScreen (XtScreen (top)),
					    Options.visual,
					    AllocNone);
		XtSetArg (args[cnt], XtNcolormap, colormap); ++cnt;

		/*
		 * Now find some information about the visual.
		 */
		vinfo.visualid = XVisualIDFromVisual (Options.visual);
		vinfo_list = XGetVisualInfo (dpy, VisualIDMask, &vinfo, &count);
		if (vinfo_list && count > 0)
		{
			XtSetArg (args[cnt], XtNdepth, vinfo_list[0].depth);
			++cnt;
			XFree ((XPointer) vinfo_list);
		}
	}
	XtDestroyWidget (top);


	/*
	 * Now create the real toplevel widget.
	 */
	XtSetArg (args[cnt], XtNargv, xargv); ++cnt;
	XtSetArg (args[cnt], XtNargc, xargc); ++cnt;
	top = XtAppCreateShell ((char *) NULL, class,
				applicationShellWidgetClass,
				dpy, args, cnt);

	/*
	 * Display the application and loop handling all events.
	 */
	XtRealizeWidget (top);
	XtAppMainLoop (app);
	return (0);
}

You can also try:

	file://ftp.x.org/contrib/widget/AppPlusS.tar.Z

The AppPlusShell adds the following to the application shell:

1) Visual/Colormap control thru resources
2) EditRes built in (can be turned on/off)
3) Catches the WM_DELETE_WINDOW

	It does this thru the following added resources:

For 1:
XtNvisualClass
XtNusePrivateColormap
XtNvisualID
XtNapplicationDepth

For 2:
XtNallowEditRes

For 3:
XtNsaveYourselfCallback



	The algorithm is as follows, in this order:

1) if XtNvisualID is set try to use the visual with this id, if
it exists.

2) if XtNapplicationDepth is set try to find a visual with 
that depth, otherwise set it to DefaultDepth().  This allows 
users to have:

*applicationDepth: 24

which will be used if it exists.  applicationDepth is needed
instead of *depth, since, IMO, most users will want to do

*depth: 24 

which would screw up for any subwidgets, if there were no visual
with a depth of 24.  Note that the depth gets correctly set in the 
initialize too.

3) if XtNvisualClass is set then find the visual with the that
class and the greatest depth.

4) if all else fails use the default visual/default depth.

5) if we the visualID == default visual id, and XtNusePrivateColormap
is FALSE, then use the default colormap, otherwise, create an
appropriate one.




	There only other thing of interest is if you define MOTIF
the code uses some Motif functions instead of their X/Xt
equivalents, but otherwise should work with pretty much any
Xt widget set.

	I use a version of this code in our product, and so it has
been used on just about every major U*x platform with success.


User Contributions:

Comment about this article, ask questions, or add new information about this topic: