bill@fedeva.UUCP (Bill Daniels) (03/09/90)
Caveat: I am a very green X programmer. I am working on an application in which the client application needs to receive input from a file/socket as well as normal events. In my environment, which is DECwindows, I have access to a call, XtAppAddInput, that will allow this to happen. I cannot of course find this documented in any generic X document which leads me to believe that it is not a portable construct. My question is how to accomplish this maneuver in a portable fashion. I hope that I am not alone in needing this capability and that someone more versed in X than I will be able to offer me some guidance. Thanks -- bill daniels federal express, memphis, tn {hplabs!csun,mit-eddie!premise}!fedeva!wrd3156
cjmchale@cs.tcd.ie (Ciaran McHale) (03/12/90)
In article <27@fedeva.UUCP> bill@fedeva.UUCP (Bill Daniels) writes: >Caveat: I am a very green X programmer. > >I am working on an application in which the client application needs to >receive input from a file/socket as well as normal events. In my environment, >which is DECwindows, I have access to a call, XtAppAddInput, that will allow >this to happen. I cannot of course find this documented in any generic >X document which leads me to believe that it is not a portable construct. >My question is how to accomplish this maneuver in a portable fashion. I hope >that I am not alone in needing this capability and that someone more versed >in X than I will be able to offer me some guidance. The X User's group (XUG) post a "frequently asked questions & answers" message to comp.windows.x once a month and they are thinking of doing so more frequently. Your problem hasn't yet made it onto the list; but I think this is more to do with the fact that the "frequently asked questions" posting has just gotten off the ground rather than it being an uncommon question. So, I'd advise you to do several things 1. Keep an eye out for the regular posting since it may prove useful for other problems. 2. Look at what I've given below --- it may appear on a future "frequently asked questions" posting. 3. Learn the difference between "Xlib" based programs and "Xt" based programs. Basically the "X Toolkit Intrinsics", commonly abbreviated to Xt, is a library built on top of Xlib. It is designed to take some of the burden off programmers. Unfortunately for you, you can't just mix and match Xlib code with Xt code at will so you won't be able to use XtAppAddInput() (which is an Xt routine) in a program that doesn't otherwise follow the Xt style of programming. While it's can be useful to be able to program in Xlib, you might find that learning how to use a toolkit will save you time in the long run. Ciaran. ------ cjmchale@cs.tcd.ie To: xug@expo.lcs.mit.edu cc: Subject: Frequently asked questions posting: A contribution -------- First off, I must say that the frequently asked questions posting is a great idea. I just that people on the net will appreciate the large amount of time it takes to maintain such a posting. > [ ** Every two weeks is fine with XUG. Suggestions? **]. Yes, I agree that the frequently asked questions posting would be more useful if posted more often. I guess that every 2 weeks is about right. I've noticed that more and more X programmers want to write X clients as graphical front ends to other compute bound process. Basically, they read data from the back end process and display it in an X window. This involves being able to handle X events and also listen for the arrival of data from the back end process. Below is my solution to the problem. I'd be pleased if you could incorporate it into the frequently asked questions posting (either in it's entirety or cut and paste it as you see fit). Note that this solution is for Xlib based programs. Perhaps somebody else will offer to tell the net how to do something similar in Xt and non-Xt based toolkits. Ciaran. ------- cjmchale@cs.tcd.ie "Send the kids off to war. At least it will keep them off the streets" --- FdB ---------------------------------- CUT HERE --------------------------------- Question: How can my Xlib based application communicate with more than one X and/or some other input source simultanously? Answer: If you're programming on a BSD UNIX type system then the following code is directly of relevence. If not, then you'll have to consult your system's manual to find an equivalent of the select() system call. To help you, the following is a brief overview of the select() call. ----------------------- start of overview on select() --------------------- int select(int nfds, int *readfds, int *writefds, int *execptfds, struct timeval *timeout); The select() call is passed in 3 bitmasks - "readfds", "writefds" and "execptfds" - the size of these bitmasks in "nfds". The bitmasks represent the file descriptors that select() is to pay attention to. It will block until there is something waiting to be read on any of the "readfds" file descriptors, or it is possible to write to any of the "writefds" file descriptors or an exception (such as "end of file") is encountered on any of the "exceptfds" file descriptors. File descriptor N is indicated by "1 << N" in the appropiate bitmask. The "timeout" parameter is used to determine the maximun amount of time that select() should block for. If a NULL pointer is passed in then select() will block indefinitely. Upon return, the select() call will overwrite the bitmasks to indicate which file descriptors are ready. Also the return value is -1 on error, or the number of ready file descriptors on success. ------------------------ end of overview on select() ----------------------- You can use the select() system call to wait until there is something waiting to be read on one of several file descriptors - it's more effecient than waiting via busy looping. So to manage 2 display connections and a socket/pipe connection simultaneously you might use a main loop of the form ... (disclaimer: I haven't tested this code) Display *display_1 = XOpenDisplay(...); Display *display_2 = XOpenDisplay(...); int other_fd = ... /* code to open a socket or pipe etc */ struct timeval zero_time; zero_time.tv_sec = 0; zero_time.tv_usec = 0; while (1) { int fd_1, fd_2; long read_mask; /* A 32 bit bitmask - HOPEFULLY big enough */ int num_fds, result; boolean got_event = FALSE; /* ** check if there are any X events waiting to be processed. ** But don't block if there isn't. */ if (XPending(display_1)) { got_event = TRUE; XNextEvent(display_1, &event); ... /* process it */ } if (XPending(display_2)) { got_event = TRUE; XNextEvent(display_2, &event); ... /* process it */ } /* ditto for display_3, display_4 ... */ /* ** check if there is any data to be read on "other_fd". ** But don't block if there isn't. */ read_mask = 1 << other_fd; num_fds = other_fd + 1; result = select(num_fds, &read_mask, /* read mask */ (int *)0, /* no write mask */ (int *)0, /* no exception mask */ &zero_time); /* don't block */ if (read_mask & (1 << other_fd)) { got_event = TRUE; /* code to read and process data */ ... } /* ditto for any other socket/pipe connections */ if (got_event) { /* back to top of while loop */ continue; } /* ** There's no events to be processed so wait until there is. ** The select system call is used for this. */ /* get the file descriptor of the Display connections */ fd_1 = ConnectionNumber(display_1); fd_2 = ConnectionNumber(display_2); /* set up the read mask for select() */ read_mask = (1 << fd_1) | (1 << fd_2) | (1 << other_fd); num_fds = max(fd_1, max(fd_2, other_fd)) + 1; result = select(num_fds, &read_mask, /* read mask */ (int *)0, /* no write mask */ (int *)0, /* no exception mask */ (struct timeval *)0); /* no timeout */ /* ** The value of "read_mask" could be checked to see ** which of the file descriptors have data waiting to ** be read. However, falling back to the top of the while ** loop will suffice . */ } /*of while*/ If you modify the above loop style then beware of the following: For various reasons (including network effeciency, I suppose) some X events which are yet to be seen are stored in a queue in main memory. Hence, even though there may be nothing to read on ConnectionNumber(display), there might be X events held locally by the Xlib data structures. So make sure to use XPending(display) before doing a blocking select call. Otherwise your program is likely to hang. The chapter on event processing in "Introduction to the X Window System", by Oliver Jones, Prentice-Hall, 1988 (ISBN 0-13-499997-5) also discusses this. ---------------------------------- CUT HERE ---------------------------------
asente@decwrl.dec.com (Paul Asente) (03/13/90)
In article <27@fedeva.UUCP> bill@fedeva.UUCP (Bill Daniels) writes: I cannot of course find this [XtAppAddInput] documented in any generic >X document which leads me to believe that it is not a portable construct. You must have very old documentation. XtAppAddInput has been in the Intrinsics since at least R3. -paul asente asente@decwrl.dec.com decwrl!asente