Don Burns (don_burns++at++peru.csd.sgi.com)
Thu, 29 Oct 1998 10:26:47 -0800 (PST)
> I want to do X event handling in a Performer application (I don't want to use
> pfu...). I do not fork an extra process for X but I need multiprocessing.
In multprocess mode, only the DRAW process has a graphics context and therefore
access to the XDisplay and XEvents. Every line of code in the example program
you included runs in APP.
Multiprocessing does not begin until pfConfig is called. Further, the DRAW
process does not connect to the display, or open a window until the first
call to pfFrame().
The remedy for this problem is similar to a recent post I sent out. Add a
config callback to the pfPipeWindow just before calling pfConfigPWin():
...
pfPWinFBConfig( pwin, myconfigfunc );
pfConfigPWin( pwin );
...
This callback will be called in the DRAW process after DRAW has connected
to the display, and opened a window, making it then legal to call
pfGetCurWSConnection()
and
xwin = pfGetPWinWSWindow(pwin);
This values should return NULL, or undefined in APP, which is where you
are currently calling them from, and should explain the multiprocess crash.
Write myconfigfunc as follows:
void myconfigfunc(pfPipeWindow *pw)
{
pw->open();
/* Put any X initialization here
(like XSelectInput()*/
}
This still does not solve your problem, though. You need to add a DRAW
callback to your channel with
pfChanTravFunc( chan, PFTRAV_DRAW, my_draw_callback );
In my_draw_callback, besides needing to clear then channel and call
pfDraw(), you can put in your XPending() block:
void draw(pfChannel *chan, void *data)
{
while( XPending( ... )
{
....
/* Be careful to use input to write to shared
memory where it can be used by app */
}
pfClearChan(chan);
pfDraw();
}
=========================================================================
Ok... there is yet a better way, for anyone who is interested. Consider
that it is legal in the X world to get events from and send requests for
a window that doesn't "belong" to your process. With this in mind, you
can watch X events happening on your pfPipeWindow in a separate process.
This process can remain blocked on XNextEvent so it can stay out of the
way of the rest of the simulation and allow your DRAW process to concentrate
on rendering and not doing pesky tasks like watching for input events.
This is a little different that the way pfu does it (which uses ATOMS),
but I would do this from the pfPipeWindow config func like this:
// From the pipeWindow Config func :
static void do_xevents( Window win );
void myPipeWindowConfigFunc( pfPipeWindow *pw )
{
int pid;
pw->open();
if( (pid = fork()) < 0 )
{
perror( "WARNING : xInput:fork" );
return;
}
else if( pid == 0 )
do_xevents( pw->getWSWindow() );
}
do_xevents( Window win )
{
Display *dpy = XOpenDisplay( "" );
XSelectInput( dpy, win, KeyPressMask );
for( ;; )
{
XEvent ev;
XNextEvent( dpy, &ev );
switch( ev.type )
{
case KeyPress:
// yada yada
}
}
}
Hope this helps,
-don
This archive was generated by hypermail 2.0b2 on Thu Oct 29 1998 - 10:27:37 PST