diff options
Diffstat (limited to 'progs/miniglx/sample_server2.c')
-rw-r--r-- | progs/miniglx/sample_server2.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/progs/miniglx/sample_server2.c b/progs/miniglx/sample_server2.c new file mode 100644 index 00000000000..3508a21950c --- /dev/null +++ b/progs/miniglx/sample_server2.c @@ -0,0 +1,227 @@ +/* $Id: sample_server2.c,v 1.1 2003/08/06 17:47:15 keithw Exp $ */ + +/* + * Sample server that just keeps first available window mapped. + * + * It also reads and echos anything that happens on stdin as an + * example of tracking events from sources other than miniglx clients. + * + * It reads & writes without blocking, so that eg. piping a lot of + * text to stdin and then hitting 'ctrl-S' on the output stream won't + * cause it to stop handling miniglx events. + * + * See select_tut in the linux manual pages for a good overview of the + * select(2) system call. + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <GL/gl.h> +#include <GL/miniglx.h> +#include <errno.h> +#include <assert.h> + +struct client { + struct client *next; + Window windowid; + int mappable; +}; + +struct client *clients = 0, *mapped_client = 0; + +#define BUFSZ 4096 +char rbuf[BUFSZ]; +int rbuf_count; + + +static struct client *find_client( Window id ) +{ + struct client *c; + + for (c = clients ; c ; c = c->next) + if (c->windowid == id) + return c; + + return 0; +} + +int main( int argc, char *argv[] ) +{ + Display *dpy; + XEvent ev; + int autostart = 0; + + if (argc == 2 && strcmp(argv[1], "-autostart") == 0) + autostart = 1; + + dpy = __miniglx_StartServer(NULL); + if (!dpy) { + fprintf(stderr, "Error: __miniglx_StartServer failed\n"); + return 1; + } + + /* How is vt switching communicated through the XNextEvent interface? + */ + while (1) { + int r, n; + struct timeval tv; + fd_set rfds, wfds; + int bored = 0; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + tv.tv_sec = 1; + tv.tv_usec = 0; + + if (rbuf_count) { + FD_SET( 1, &wfds ); /* notify when we can write out buffer */ + n = 1; + } + else { + FD_SET( 0, &rfds ); /* else notify when new data to read */ + n = 0; + } + + /* __miniglx_Select waits until any of these file groups becomes + * readable/writable/etc (like regular select), until timeout + * expires (like regular select), until a signal is received + * (like regular select) or until an event is available for + * XCheckMaskEvent(). + */ + r = __miniglx_Select( dpy, n+1, &rfds, &wfds, 0, &tv ); + + /* This can happen if select() is interrupted by a signal: + */ + if (r < 0 && errno != EINTR && errno != EAGAIN) { + perror ("select()"); + exit (1); + } + + if (tv.tv_sec == 0 && tv.tv_usec == 0) + bored = 1; + + /* Check and handle events on our local file descriptors + */ + if (FD_ISSET( 0, &rfds )) { + /* Something on stdin */ + assert(rbuf_count == 0); + r = read(0, rbuf, BUFSZ); + if (r < 1) { + perror("read"); + abort(); + } + rbuf_count = r; + } + + if (FD_ISSET( 1, &wfds )) { + /* Can write to stdout */ + assert(rbuf_count > 0); + r = write(1, rbuf, rbuf_count); + if (r < 1) { + perror("write"); + abort(); + } + rbuf_count -= r; + if (rbuf_count) + memmove(rbuf + r, rbuf, rbuf_count); + } + + + /* Check and handle events generated by miniglx: + */ + while (XCheckMaskEvent( dpy, ~0, &ev )) { + struct client *c; + bored = 0; + + fprintf(stderr, "Received event %d\n", ev.type); + + switch (ev.type) { + case CreateNotify: + fprintf(stderr, "CreateNotify -- new client\n"); + c = malloc(sizeof(*c)); + c->next = clients; + c->windowid = ev.xcreatewindow.window; + c->mappable = False; + clients = c; + break; + + case DestroyNotify: + fprintf(stderr, "DestroyNotify\n"); + c = find_client(ev.xdestroywindow.window); + if (!c) break; + if (c == clients) + clients = c->next; + else { + struct client *t; + for (t = clients ; t->next != c ; t = t->next) + ; + t->next = c->next; + } + + if (c == mapped_client) + mapped_client = 0; + + free(c); + break; + + case MapRequest: + fprintf(stderr, "MapRequest\n"); + c = find_client(ev.xmaprequest.window); + if (!c) break; + c->mappable = True; + break; + + case UnmapNotify: + fprintf(stderr, "UnmapNotify\n"); + c = find_client(ev.xunmap.window); + if (!c) break; + c->mappable = False; + if (c == mapped_client) + mapped_client = 0; + break; + + default: + break; + } + } + + + /* Search for first mappable client if none already mapped. + */ + if (!mapped_client) { + struct client *c; + for (c = clients ; c ; c = c->next) { + if (c->mappable) { + XMapWindow( dpy, c->windowid ); + mapped_client = c; + break; + } + } + if (!clients && autostart) { + system("nohup ./texline &"); + system("nohup ./manytex &"); + } + } + else if (bored) { + struct client *c; + /* bored of mapped client now, let's try & find another one */ + for (c = mapped_client->next ; c && !c->mappable ; c = c->next) + ; + if (!c) + for (c = clients ; c && !c->mappable ; c = c->next) + ; + if (c && c != mapped_client) { + XUnmapWindow( dpy, mapped_client->windowid ); + XMapWindow( dpy, c->windowid ); + mapped_client = c; + } + else + fprintf(stderr, "I'm bored!\n"); + } + } + + XCloseDisplay( dpy ); + + return 0; +} |