📄 ch60.htm
字号:
white = AllocNamedColor(display, PEX_colormap,
"White", 0L);
n = 0;
XtSetArg(args[n],XmNvisual, visual); n++;
XtSetArg(args[n],XmNdepth, depth); n++;
XtSetArg(args[n],XmNcolormap, colormap); n++;
XtSetArg(args[n],XmNallowResize, True); n++;
XtSetArg(args[n],XmNmapWhenManaged, False); n++;
XtSetArg(args[n],XmNbackground, blue); n++;
XtSetArg(args[n],XmNforeground, white); n++;
XtSetArg(args[n],XmNargc, cp_argc); n++;
XtSetArg(args[n],XmNargv, cp_argv); n++;
XtSetArg(args[n],XmNheight, 400); n++;
XtSetArg(args[n],XmNwidth, 400); n++;
toplevel = XtAppCreateShell(NULL, "peX",
applicationShellWidgetClass, display, args, n);
mainWindow = XmCreateMainWindow(toplevel, "mainWin", NULL, 0);
drawMe = XmCreateDrawingArea(mainWindow,
"pexdraw", args, n);
</FONT></PRE>
<DL>
<DT><FONT COLOR="#0066FF"></FONT></DT>
</DL>
<DL>
<DD>
<HR>
<A NAME="Heading19<FONT COLOR="#000077"><B>TIP: </B></FONT>If you are unfamiliar
with programming in Motif or X, refer to Chapter 34, "Motif Programming."
<HR>
</DL>
<P>The application requires the <TT>toplevel</TT> shell. For this shell, you have
to manually set its visual, screen, display, and colormap. Note that the resize resource
is set to True and <TT>mapWhenManaged</TT> is set to False. You have to set these
values via the <TT>XtArgs</TT> <TT>args</TT> array at creation time for this to work.
The <TT>toplevel</TT> shell is where you create the main window to place your Motif
widgets. After you have created the main window with the <TT>XmCreateMainWindow</TT>
function call, you create the drawing area called <TT>drawMe</TT> on top of this
window.</P>
<P>Next, you add callbacks to the drawing area widget to allow for redrawing. Add
the callbacks to the drawing area for the following types of events: <TT>resize</TT>,
<TT>expose</TT>, and <TT>input</TT>.</P>
<P>The complete code for a very simple application is shown in Listing 60.2.
<CENTER>
<H3><A NAME="Heading20<FONT COLOR="#000077">Listing 60.2. A sample PEX application
with Motif.</FONT></H3>
</CENTER>
<PRE><FONT COLOR="#0066FF">
#include <Xm/Xm.h>
#include <Xm/DrawingA.h>
#include <Xm/MainW.h>
#include <Xm/RowColumn.h>
#include <X11/PEX5/PEXlib.h>
#include <stdio.h>
int bailout(char *str)
{
printf ("\n %s", str);
exit(1);
}
int pex_set_line_color(Display *dpy, PEXRenderer p,
float r, float g, float b)
{
PEXColor pc;
pc.rgb.red = r;
pc.rgb.green = g;
pc.rgb.blue = b;
PEXSetLineColor(dpy, p, PEXOCRender, PEXColorTypeRGB, &pc);
}
void doSamplePEX( Display *dpy, Window win, PEXRenderer ren)
{
PEXCoord coords[10];
PEXBeginRendering(dpy, win, ren);
PEXSetLineWidth(dpy, ren, PEXOCRender, 8.0);
pex_set_line_color(dpy, ren, 0.5, 0.5, 1.0);
coords[0].x = 0.3; coords[0].y = 0.3; coords[0].z = 0.0;
coords[1].x = 0.3; coords[1].y = 0.6; coords[1].z = 0.0;
coords[2].x = 0.6; coords[2].y = 0.6; coords[2].z = 0.0;
coords[3].x = 0.6; coords[3].y = 0.3; coords[3].z = 0.0;
PEXPolyline(dpy, ren, PEXOCRender, 4, coords);
pex_set_line_color(dpy, ren, 1.5, 0.5, 1.5);
coords[0].x = 0.3; coords[0].y = 0.3; coords[0].z = 0.5;
coords[1].x = 0.3; coords[1].y = 0.6; coords[1].z = 0.5;
coords[2].x = 0.6; coords[2].y = 0.6; coords[2].z = 0.5;
coords[3].x = 0.6; coords[3].y = 0.3; coords[3].z = 0.5;
PEXPolyline(dpy, ren, PEXOCRender, 4, coords);
PEXEndRendering(dpy, win, ren);
XFlush(dpy); /* important */
}
void quitBtn( Widget w, void *p, void *pp)
{
exit(0);
}
void drawBtn( Widget w, XmDrawingAreaCallbackStruct *sp,
XtPointer *client_data)
{
Dimension wd, ht;
PEXRenderer *rp;
if (sp == NULL) return;
switch(sp->reason)
{
case XmCR_EXPOSE:
if (sp->event->xexpose.count == 0)
{
rp = (PEXRenderer *)client_data;
doSamplePEX(XtDisplay(w), XtWindow(w), *rp);
}
break;
case XmCR_INPUT:
break;
}
}
int
pexInit(Display *dpy, PEXExtensionInfo **pexparms)
{
int err;
char errorMsg[PEXErrorStringLength+1];
PEXExtensionInfo *pex_info;
err = PEXInitialize(dpy, pexparms,
PEXErrorStringLength, errorMsg);
if (err) return False;
pex_info = (PEXExtensionInfo *)(*pexparms);
if( (pex_info->subset_info & PEXImmediateMode) ||
((pex_info->subset_info & 0xffff) == PEXCompleteImplementation))
{
return True;
}
return False;
}
int main(int argc, char *argv[])
{
Widget parent;
XtAppContext app_context;
int cp_size;
int cp_argc;
int cp_argv;
int status;
int screen;
int depth;
int fore;
int bkg;
int n;
Arg wars[20];
Visual *visual;
Colormap colormap;
XStandardColormap std_cmp;
PEXRendererAttributes pex_attr;
Display *dpy;
PEXExtensionInfo *pexParms;
PEXRenderer ren;
Widget mainw;
Widget filemenu;
Widget menubar;
Widget exitBtn;
Widget drawme;
XtToolkitInitialize();
app_context = XtCreateApplicationContext();
cp_argc = argc;
cp_size = argc * (sizeof(char *));
cp_argv = (char **)XtMalloc(cp_size);
memcpy(cp_argv, argv, cp_size);
dpy = XtOpenDisplay(app_context, NULL, NULL,
"pexSample", NULL, 0, &argc, argv);
if (dpy == (Display *) NULL)
bailout("Cannot open display");
status = pexInit(dpy,&pexParms);
if (status == False) bailout("Cannot use PEX");
screen = DefaultScreen(dpy);
visual = DefaultVisual(dpy, screen);
depth = DefaultDepth(dpy,screen);
status = GetStdColormap(dpy, screen, visual, depth, &std_cmp);
colormap = std_cmp.colormap;
bkg = BlackPixel(dpy,screen);
fore = WhitePixel(dpy,screen);
n = 0;
XtSetArg(wars[n], XmNvisual, visual); n++;
XtSetArg(wars[n], XmNdepth, depth); n++;
XtSetArg(wars[n], XmNcolormap, colormap); n++;
XtSetArg(wars[n], XmNbackground, bkg); n++;
XtSetArg(wars[n], XmNborderColor, fore); n++;
XtSetArg(wars[n], XmNargc, cp_argc); n++;
XtSetArg(wars[n], XmNargv,cp_argv); n++;
XtSetArg(wars[n], XmNallowResize, True); n++;
XtSetArg(wars[n], XmNmappedWhenManaged, False); n++;
XtSetArg(wars[n], XmNwidth, 300); n++;
XtSetArg(wars[n], XmNheight, 300); n++;
parent = XtAppCreateShell(NULL,"pexSample",
applicationShellWidgetClass, dpy, wars, n);
n = 0;
mainw = XmCreateMainWindow(parent, "mainwindow", wars, n);
n = 0;
XtSetArg(wars[n], XmNresizePolicy, XmRESIZE_ANY); n++;
XtSetArg(wars[n], XmNbackground, bkg); n++;
XtSetArg(wars[n], XmNborderColor, fore); n++;
drawme = XmCreateDrawingArea(mainw, "da", wars, n);
XtAddCallback(drawme, XmNexposeCallback,
(XtCallbackProc)drawBtn, (XtPointer) &ren);
XtAddCallback(drawme, XmNinputCallback,
(XtCallbackProc)drawBtn, (XtPointer) &ren);
XtAddCallback(drawme, XmNresizeCallback,
(XtCallbackProc)drawBtn, (XtPointer) &ren);
XtManageChild(drawme);
XtManageChild(mainw);
XtRealizeWidget(parent);
pex_set_color_approx(dpy,XtWindow(drawme), &std_cmp, &pex_attr);
XtMapWidget(parent);
ren = PEXCreateRenderer(XtDisplay(mainw), XtWindow(drawme),
PEXRAColorApproxTable, &pex_attr);
if (ren == 0) {
printf("\n Bad renderer \n"); exit (1);
}
XtAppMainLoop(app_context);
return(0);
}
</FONT></PRE>
<P>A few points to note about Listing 60.2 are that the <TT>immediate</TT> mode was
used for rendering on the screen. PEX-SI provides no support for double buffering.
This is a serious bug because lack of double buffering hinders performance.</P>
<P>Even worse, the PEX-SI API assumes that the client desires an <TT>XClearArea</TT>
on the window before each frame is drawn. This causes unnecessary flickering while
the screen is cleared and redrawn on all primitive drawing calls. What should have
been done was to provide an end-of-render procedure hook, with the default hook installed
to do a clear area function call.</P>
<P>Individual vendors (because of market pressure) have provided their own solutions
to the double buffering problem. (Most PHIGS workstations do double buffering. If
you do <TT>immediate</TT> mode you get single buffering along with the PEX-SI's <TT>XClearArea</TT>
call.)</P>
<P>A final word about adding too many features in an X server. The more you add to
the X server, the more memory it chews up in your system. Unless you absolutely require
PEX (or other) support, do not add it to your X server, especially if RAM is 8MB
or less. The PEX support for Linux added about 420KB on my system, which is not a
lot, but it does start adding up. Also, the overhead of PEX applications tend to
make my 8MB, 486/33 somewhat slow when running PEX demos, which leads me to believe
that PEX on Linux with less than 16MB is not worth the hassle. If you are serious
about PEX on Linux, get a faster machine and put gobs of memory on it. The performance
improved very dramatically on a 486/66 with 32MB of RAM.
<CENTER>
<H3><A NAME="Heading22<FONT COLOR="#000077">Where to Look for More Information</FONT></H3>
</CENTER>
<P>If you would like more information and examples of source code for PEX, check
out these FTP sites:
<UL>
<LI><TT>export.lcs.mit.edu</TT> in <TT>/R5contrib/contrib-R5fixes</TT> has several
<TT>tar</TT> files of source code for PHIGS and PEX including a 3-D drawing program.
<P>
<LI><TT>http://www.x.org</TT> is a good place to start looking for more information
on X.
</UL>
<CENTER>
<H3><A NAME="Heading23<FONT COLOR="#000077">Summary</FONT></H3>
</CENTER>
<P>This chapter has been a whirlwind tour of PEX. The topic of PEX could be a book
in itself. In fact, there are several texts available that go into excruciating detail
about PEX. You should have learned the following information from this chapter:
<UL>
<LI>How to create a new X server with your specifications. Building your own server
with LinkKit is far easier than trying to re-create the entire X distribution. There
are fewer memory requirements, and the build takes up less disk space and time to
compile and link.
<P>
<LI>How to install the new server. The LinkKit does this for you automatically and
gives you options to clean your directories, and so on.
<P>
<LI>How to check for the extensions in the current server.
<P>
<LI>How to interface Motif with PEX.
<P>
<LI>The trade-offs of having too many extensions in X server, such as loss of memory
and speed for added functionality.
<P>
<LI>Where to look for more information about PEX and Linux.
</UL>
</td>
</tr>
</table>
<!-- begin footer information -->
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -