[comp.windows.x] Event Loops

cookson@helios.mitre.org (Cookson) (05/30/90)

First off let me say thank you to all the people who replied to my first 
message.  Now for a slight clarification of my problem.
I'm avoiding an event loop by doing the following.


#include	"toolkit.h"
Display *mydisplay;
int	childpid;
int	fd;
end();

Event_Loop()
{

	while(XEventsQueued(mydisplay, QueuedAfterReading)) {
		XEvent	myevent;

		XtNextEvent(&myevent);
		XtDispatchEvent(myevent);
	}
}

Initialize_Toolkit(int argc, char *argv[])
{

  Widget control_shell, control_board, tracker_select, tracker_form;
  Widget start_button, quit_button;
  Arg wargs[2];
  
  /* Initialize the toolkit, and create the shell for the control window. */
  control_shell = XtInitialize(argv[0], "Xradar", NULL, 0, &argc, argv);
  mydisplay = XtDisplay(control_shell);
  fd = ConnectionNumber(mydisplay);
  fcntl(fd, F_SETOWN, getpid());
  fcntl(fd, F_SETFL, FASYNC);
  signal(SIGIO, Event_Loop);
  /*	Create all my widgets, etc... */
}

The problem is that when Event_Loop gets called, XEventsQueued() claims
that there are no events in the queue.  (Yes XtPending() says the same thing).
Now, it's obvious that I'm either blind or stupid (or both), and that I'm
missing something painfully obvious.  But the question is what????

Thanks in Advance,
Dean


% Dean Cookson				  $ Anyone can be taught to sculpt    %
% dcookson@mitre.org			    $ Michaelangleo would have had to %
% {devax,et al..}!linus!mbunix!helios!cookson $ have been taught how not to.  %
% Disclaimer: My opinions are my own, and       $ The same is true of great   %
%       are of questionable sanity                $ programmers               %

nancie@hal.CSS.GOV (Nancie Matson) (08/30/90)

I am trying to implement an event loop in my Xt application,
(in addition to XtMainLoop) to capture input from a list
of popup toggle widgets.  I am using XtNextEvent to retrieve
the next event on the queue, and them I am testing it to
see if it is one of the widgets I am looking for.

The problem I get occurs before the Event Loop is 
executed.  Whatever I try to do  immediately before
this EventLoop, doesn't get executed.   For example, if
I want to display a message to the user by changing
a label widget, and then execute the Event Loop, I never
see the message on the screen.

I know this has to do with the server not recieving the last
event on the queue (XtMainLoop's queue), but I tried using
XFlush, and XSync before executing my event loop with no
luck.  

The following is a sample of my event Loop.

-------
       strcpy(label,"Select an Event with the mouse.");
       XtSetArg (args[0],XtNlabel,label);
       XtSetValues(status,args,1);

       while (!done)
       {
          XtNextEvent(&event);
          if (event.type == ButtonPress)
          {
             if (((event.xbutton.button == Button1) ||
                  (event.xbutton.button == Button2) ||
                  (event.xbutton.button == Button3)) &&
                  (event.xbutton.window == XtWindow(evnt.data[j].esym)))
             {
                point = Project (1,map.proj->id,evnt.data[j].loc,0);
                loc->x = (int)point.xlon;
                loc->y = (int)point.ylat;
                done = 1;
                *index = j;
             }
          }
       }
       strcpy(label,"Mouse Ready ...");
       XtSetArg (args[0],XtNlabel,label);
       XtSetValues(status,args,1);

----------

The first call to XtSetValues doesn't appear on the screen, but the second
one does.  Is there any way to ensure that events/server requests placed
on the queue before a call to XtNextEvent get executed?

Any info would be helpful.  SO far I've tried using XtFlush, XtSync and
even XtDispatchEvent.

Please e-mail to nancie@hal.CSS.GOV.  I will post a summary if anyone
is interested.

-Nancie P. Matson
 ENSCO, Inc.
 nancie@hal.CSS.GOV

malbert@jeeves.shearson.com (Marc Albert) (04/13/91)

I have an application that has multiple top level windows.  The event
loop looks something like this:


	for (;;) {
		if (XtAppPending(WindowOne))
			XtDispatch();

		if (XtAppPending(WindowTwo))
			XtDispatch();
	}

This method works fine.  The only problem I have is that 
I have to poll for events; this means I am never really 
waiting (blocking) and I am burning a lot of CPU.  Is there
a better method.  The only thing I can think of is to
create two separate executables - I don't want to have to
do that.

Any suggestions would be welcome.  Thanks.

Marc.


return address  	...uunet!shearson.com!malbert
MA Bell:		(212) 464-3061

klee@wsl.dec.com (Ken Lee) (04/13/91)

In article <MALBERT.91Apr12135341@jeeves.shearson.com>, malbert@jeeves.shearson.com (Marc Albert) writes:
|> I have an application that has multiple top level windows.  The event
|> loop looks something like this:
|> 	for (;;) {
|> 		if (XtAppPending(WindowOne))
|> 			XtDispatch();
|> 		if (XtAppPending(WindowTwo))
|> 			XtDispatch();
|> 	}
|> 
|> This method works fine. 

Are you sure this works?  XtAppPending takes an application context,
not a window, as its argument.  The application context can contain any
number of displays, with each display containing any number of
top-level windows.


-- 
Ken Lee
DEC Western Software Laboratory, Palo Alto, Calif.
Internet: klee@wsl.dec.com
uucp: uunet!decwrl!klee

malbert@jeeves.shearson.com (Marc Albert) (04/15/91)

|> I have an application that has multiple top level windows.  The event
|> loop looks something like this:
|> 	for (;;) {
|> 		if (XtAppPending(WindowOne))
|> 			XtDispatch();
|> 		if (XtAppPending(WindowTwo))
|> 			XtDispatch();
|> 	}
|> 
|> This method works fine. 

>Are you sure this works?  XtAppPending takes an application context,
>not a window, as its argument.  The application context can contain any
>number of displays, with each display containing any number of
>top-level windows.

I'm sorry if my example was unclear.  This was supposed to be
just a sample of the logic - not actual code.  You are correct,
that application does use multiple application contexts.

Marc.



return address   	...uunet!shearson.com!malbert
MA Bell:		(212) 464-3061

marbru@auto-trol.com (Martin Brunecky) (04/17/91)

In article <MALBERT.91Apr15105521@jeeves.shearson.com> malbert@jeeves.shearson.com (Marc Albert) writes:
>
>I'm sorry if my example was unclear.  This was supposed to be
>just a sample of the logic - not actual code.  You are correct,
>that application does use multiple application contexts.
>
    I am curious. WHY do you need MULTIPLE application contexts
    in a SINGLE Xt application ?
    [I always assumed that application context is required for
     multi-threaded environments, where the same Xt code/data
     is used in multiple contexts - is this your case ? ]



-- 
=*= Opinions presented here are solely of my own and not those of Auto-trol =*=
Martin Brunecky                           {...}sunpeaks!auto-trol!marbru
(303) 252-2499                        (sometimes also:  marbru@auto-trol.COM )
Auto-trol Technology Corp. 12500 North Washington St., Denver, CO 80241-2404 

bschoen@well.sf.ca.us (Brook Schoenfield) (04/18/91)

malbert@jeeves.shearson.com (Marc Albert) writes:

>I have an application that has multiple top level windows.  The event
>loop looks something like this:


>	for (;;) {
>		if (XtAppPending(WindowOne))
>			XtDispatch();

>		if (XtAppPending(WindowTwo))
>			XtDispatch();
>	}

>This method works fine.  The only problem I have is that 
>I have to poll for events; this means I am never really 
>waiting (blocking) and I am burning a lot of CPU.  

XtAppPending() returns whether or not an event is avaliable:
why not use XtAppNextEvent(), which blocks until an event is
available?

If you need to do processing while waiting for user events, you
can set up a timer event and callback to do the background processing.
Do not use idle events: they will be sent as fast as the machine upon
which you run can go: thus putting you right back to the same place.

Happy Coding



Brook Schoenfield
bschoen@well.sf.ca.us

"How can our technology be used to create a peaceful, well
fed world?" - burning question

janzen@mprgate.mpr.ca (Martin Janzen) (04/18/91)

In article <24267@well.sf.ca.us>, bschoen@well.sf.ca.us (Brook Schoenfield) writes:
>malbert@jeeves.shearson.com (Marc Albert) writes:
>>I have an application that has multiple top level windows.  The event
>>loop looks something like this:
>
>>	for (;;) {
>>		if (XtAppPending(WindowOne))
>>			XtDispatch();
>
>>		if (XtAppPending(WindowTwo))
>>			XtDispatch();
>>	}
>>
>>This method works fine.  The only problem I have is that 
>>I have to poll for events; this means I am never really 
>>waiting (blocking) and I am burning a lot of CPU.  
>
>XtAppPending() returns whether or not an event is avaliable:
>why not use XtAppNextEvent(), which blocks until an event is
>available?

(I've just been digging through NextEvent.c, trying to get X apps to work as
RPC clients and servers -- so I'll throw in my $0.02 worth.)

Be careful with this.  If your application contexts (call them app1 and app2)
are connected to different displays, and you call XtAppNextEvent(app1, &event)
when no events are pending on the display connection for app1, then your
process will block until the next event is received on *that* connection.
No events in app2 will be processed until an event occurs on the display
connection for app1.

This happens because XtAppNextEvent() does a select() on the file descriptors
for all displays *in the specified application context*.  Iff both of your
application contexts share the same display connection (Is this possible?  How
would you set this up anyway?), then XtAppNextEvent() should work.

O'Reilly (Vol. 4, 13.6) discusses multiple application contexts a little, but
doesn't present a real solution to this problem, so get ready for some
experimentation!

You could try blocking by doing your own select() on the file descriptors for
the display connections in each application context, something like this:

  #include <sys/types.h>
  #include <sys/time.h>

  int     dtablesize;
  fd_set  display_fds;
  int     fd_width;
  fd_set  read_mask;
    ...

  /* after you've opened displays d1 and d2 in each application context: */
  fd_width = getdtablesize();
  FD_ZERO(&display_fds);
  FD_SET(ConnectionNumber(d1), &display_fds);
  FD_SET(ConnectionNumber(d2), &display_fds);
    ...

  /* in your main loop, if no events are pending in either app context: */
  read_mask = display_fds;
  select(fd_width, &read_mask, NULL, NULL, NULL);

(Note that if you want to use XtAddTimeOut, XtAddInput, or XtAddWorkProc as well,
then things become even more complicated -- see NextEvent.c for the gory details!)

Alternatively, you could just try adding a short usleep() if no events are
pending in either application context.  Not pretty, but better than burning
all your CPU cycles!

>If you need to do processing while waiting for user events, you
>can set up a timer event and callback to do the background processing.
>[...]

You didn't mention this in the original message, but anyone who needs to do
background processing should check out XtAddWorkProc/XtRemoveWorkProc...

>Happy Coding
Ditto!

-- 
Martin Janzen                     janzen@mprgate.mpr.ca (134.87.131.13)
MPR Teltech Ltd.                  Phone: (604) 293-5309
8999 Nelson Way                   Fax: (604) 293-5787
Burnaby, BC, CANADA  V5A 4B5

bschoen@well.sf.ca.us (Brook Schoenfield) (04/21/91)

janzen@mprgate.mpr.ca (Martin Janzen) writes:
>>      for (;;) {
>>              if (XtAppPending(WindowOne))
>>                      XtDispatch();
>
>>              if (XtAppPending(WindowTwo))
>>                      XtDispatch();
>>      }
>>
>>This method works fine.  The only problem I have is that 
>>I have to poll for events; this means I am never really 
>>waiting (blocking) and I am burning a lot of CPU.  
>
>>XtAppPending() returns whether or not an event is avaliable:
>>why not use XtAppNextEvent(), which blocks until an event is
>>available?

>Be careful with this.  If your application contexts (call them app1 and app2)
>are connected to different displays, and you call XtAppNextEvent(app1, &event)
>when no events are pending on the display connection for app1, then your
>process will block until the next event is received on *that* connection.
>No events in app2 will be processed until an event occurs on the display
>connection for app1.


Thanks much for the correcttion on the multiple display problem: I forgot about
blocking the second display.

>You didn't mention this in the original message, but anyone who needs to do
>background processing should check out XtAddWorkProc/XtRemoveWorkProc...

As long as you don't expect these calls to to take care of timeing: 
this is exactly what I
refered to in my first posting: these will be sent out as fast and as
furiously as possible.  If all you do is get one of these, do your work
and then set up the next one you will be in the same position as your first
problem.  You will tie the machine up completely.  

Good Luck


-- 


Brook Schoenfield
bschoen@well.sf.ca.us

"How can our technology be used to create a peaceful, well
fed world?" - burning question