achoi@cory.Berkeley.EDU (Andrew Choi) (12/03/90)
Hi everyone.
I am writing this program which is supposed to wait for KeyPress
events from more than 1 display, however, after thinking about
it for a long long time, I don't really know how to do it.
Please enlighten me.
To be more concrete, here's what I will do if I only have 1
display:
for (;;) {
XNextEvent(display, &event);
}
However, how do you achieve the same thing for multiple displays?
I don't want to do a wait on all the displays, I want it to return
when there is at least 1 display which has the event available.
Thanks in advance.
Name: Andrew Choi Internet Address: achoi@cory.berkeley.edu
Tel: (415)848-5658
#include <standard/disclaimer.h>
truesdel@nas.nasa.gov (David A. Truesdell) (12/03/90)
achoi@cory.Berkeley.EDU (Andrew Choi) writes: >I am writing this program which is supposed to wait for KeyPress >events from more than 1 display, however, after thinking about >it for a long long time, I don't really know how to do it. >Please enlighten me. >To be more concrete, here's what I will do if I only have 1 >display: > for (;;) { > XNextEvent(display, &event); > } >However, how do you achieve the same thing for multiple displays? >I don't want to do a wait on all the displays, I want it to return >when there is at least 1 display which has the event available. If you are running on a system which supports select(2), you can use it and ConnectionNumber() to monitor multiple displays. An example of how to do this is in "Introduction to the X Window System" by Oliver Jones. (Not an endorsement, I just happen to have it laying on my desk.) -- T.T.F.N., dave truesdell (truesdel@prandtl.nas.nasa.gov) "Courage is the willingness of a person to stand up for his beliefs in the face of great odds. Chutzpah is doing the same thing wearing a Mickey Mouse hat."
jimf@SABER.COM (12/03/90)
|I am writing this program which is supposed to wait for KeyPress |events from more than 1 display, however, after thinking about |it for a long long time, I don't really know how to do it. |Please enlighten me. You should use select, something like this: #include <sys/types.h> #include <sys/time.h> fd_set readfds; FD_ZERO(&readfds); FS_SET(ConnectionNumber(display1), &readfds); FS_SET(ConnectionNumber(display2), &readfds); for (;;) { switch(select(dtablesize(), &readfds, NULL, NULL, NULL)) { case -1: if (errno == EINTR) continue; perror("select"); exit(1); case 0: continue; default: if (FD_ISSET(ConnectionNumber(display1), &readfds)) { while (XPending(display1)) XNextEvent(display1, &event); /* do your thing here */ } if (FD_ISSET(ConnectionNumber(display2), &readfds)) { while (XPending(display1)) XNextEvent(display1, &event); /* do your thing here */ } } } jim frost saber software jimf@saber.com
etaylor@wilkins.iaims.bcm.tmc.edu (Eric Taylor) (12/04/90)
With mulitple displays, you have to use select. If you are not familiar with it, refer to UNIX documentation. Essentially, use select on all of the file descriptors of the displays you have open. When data is avaliable on one of them, do your XNextEvent on it. Be careful to make sure that XPending is 0 on all displays before calling select. for ever busy = False ; for each display dpy if XPending(dpy) > 0 XNextEvent(dpy,&event) Process event busy = True end if end for if not busy Construct fdset of all displays select(...,&fdset,...) for each display dpy that had activity XNextEvent(dpy,&event) Process event end for end if end for -- Eric Taylor Baylor College of Medicine etaylor@wilkins.bcm.tmc.edu (713) 798-3776
etaylor@wilkins.iaims.bcm.tmc.edu (Eric Taylor) (12/04/90)
Does XPending actually check the connection for requests or does it merely look at the queue of events stored in memory? If it only looks at memory, you have to check XPending for all connections before using select. -- Eric Taylor Baylor College of Medicine etaylor@wilkins.bcm.tmc.edu (713) 798-3776
mouse@LARRY.MCRCIM.MCGILL.EDU (12/04/90)
> I am writing this program which is supposed to wait for KeyPress > events from more than 1 display, however, after thinking about it for > a long long time, I don't really know how to do it. Please enlighten > me. It's system-dependent. I don't know enough about toolkits to say for sure, but I would hope that most/all toolkits would provide some way of doing this. On BSD UNIX (or other Unices which have been BSDified enough to have select()), the canonical way of doing this is to gobble up all events that are available on the connections, then select() waiting for something to arrive. > To be more concrete, here's what I will do if I only have 1 display: > for (;;) { > XNextEvent(display, &event); > } Well, you also need to do something with the event; just reading it isn't going to be very useful. I have a program that speaks to multiple displays. Here is its event loop, with irrelevant code stripped out. (The real function is about twice as big as what you see here; it does input from another file descriptor, and timeouts, in this loop as well.) (DISP_INFO is a typedef referring to my structure containing all the interesting information about each connection. disps is a global pointer to a linked list of these structures.) #define EACH_DISP(var) var=disps;var;var=var->link run() { XEvent e; DISP_INFO *d; int selrv; int wantflush; int wantupd; fd_set fds; int selcnt; int mustcontinue; struct timeval *tvp; for (EACH_DISP(d)) d->xfd = XConnectionNumber(d->disp); wantflush = 1; wantupd = 0; while (1) { mustcontinue = 0; for (EACH_DISP(d)) { if (XQLength(d->disp) > 0) { do { XNextEvent(d->disp,&e); handle_event(&e); } while (XQLength(d->disp) > 0); wantupd = 1; mustcontinue = 1; } } if (mustcontinue) continue; FD_ZERO(&fds); for (EACH_DISP(d)) FD_SET(d->xfd,&fds); if (wantflush || wantupd) { static struct timeval ztv; ztv.tv_sec = 0; ztv.tv_usec = 0; tvp = &ztv; } else { tvp = 0; } selrv = select(FD_SETSIZE,&fds,(fd_set *)0,(fd_set *)0,tvp); if (selrv < 0) { if (errno == EINTR) continue; perror("select"); utexit(1); } if (selrv == 0) { if (wantupd) { update_display(); wantflush = 1; wantupd = 0; } if (wantflush) { for (EACH_DISP(d)) XFlush(d->disp); if (debugging) fflush(stdout); wantflush = 0; } continue; } for (EACH_DISP(d)) { if (FD_ISSET(d->xfd,&fds)) { int bpend; ioctl(d->xfd,FIONREAD,&bpend); if (bpend == 0) /* socket EOF */ { utexit(0); } XEventsQueued(d->disp,QueuedAfterReading); } } } } der Mouse old: mcgill-vision!mouse new: mouse@larry.mcrcim.mcgill.edu
black@yoyodyne..westford.ccur.com (Sam Black) (12/04/90)
One thing to be careful of (I just got caught by this yesterday) is to call XFlush(dpy) on each display before calling select. You can't just call XFlush after processing all events on a display, because an event on one display may cause activity on another display. - sam ------------------------------------------------------------------------------- Once you remove the absurdity from human existence, there isn't much left. __________ / _______/__ ...!{decvax,uunet}!masscomp!black /__/______/ / black@westford.ccur.com Concurrent /_________/ Computer Corporation -------------------------------------------------------------------------------