OSDN Git Service

Merge branch 'new-frag-attribs'
[android-x86/external-mesa.git] / progs / miniglx / sample_server2.c
1
2 /*
3  * Sample server that just keeps first available window mapped.
4  * 
5  * It also reads and echos anything that happens on stdin as an
6  * example of tracking events from sources other than miniglx clients.
7  * 
8  * It reads & writes without blocking, so that eg. piping a lot of
9  * text to stdin and then hitting 'ctrl-S' on the output stream won't
10  * cause it to stop handling miniglx events.
11  *
12  * See select_tut in the linux manual pages for a good overview of the 
13  * select(2) system call.
14  */
15
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <GL/gl.h>
22 #include <GL/miniglx.h>
23 #include <errno.h>
24 #include <assert.h>
25
26 struct client {
27    struct client *next;
28    Window windowid;
29    int mappable;
30 };
31
32 struct client *clients = 0, *mapped_client = 0;
33
34 #define BUFSZ 4096
35 char rbuf[BUFSZ];
36 int rbuf_count;
37
38
39 static struct client *find_client( Window id )
40 {
41    struct client *c;
42
43    for (c = clients ; c ; c = c->next)
44       if (c->windowid == id)
45          return c;
46
47    return 0;
48 }
49
50 int main( int argc, char *argv[] )
51 {
52    Display *dpy;
53    XEvent ev;
54    int autostart = 0;
55
56    if (argc == 2 && strcmp(argv[1], "-autostart") == 0)
57       autostart = 1;
58
59    dpy = __miniglx_StartServer(NULL);
60    if (!dpy) {
61       fprintf(stderr, "Error: __miniglx_StartServer failed\n");
62       return 1;
63    }
64
65    /* How is vt switching communicated through the XNextEvent interface?
66     */
67    while (1) {
68       int r, n;
69       struct timeval tv;
70       fd_set rfds, wfds;
71       int bored = 0;
72
73       FD_ZERO(&rfds);
74       FD_ZERO(&wfds);
75       tv.tv_sec = 1;
76       tv.tv_usec = 0;
77
78       if (rbuf_count) {
79          FD_SET( 1, &wfds );    /* notify when we can write out buffer */
80          n = 1;
81       }
82       else {
83          FD_SET( 0, &rfds );    /* else notify when new data to read */
84          n = 0;
85       }
86
87       /* __miniglx_Select waits until any of these file groups becomes
88        * readable/writable/etc (like regular select), until timeout
89        * expires (like regular select), until a signal is received
90        * (like regular select) or until an event is available for
91        * XCheckMaskEvent().
92        */
93       r = __miniglx_Select( dpy, n+1, &rfds, &wfds, 0, &tv );
94
95       /* This can happen if select() is interrupted by a signal:
96        */
97       if (r < 0 && errno != EINTR && errno != EAGAIN) {
98          perror ("select()");
99          exit (1);
100       }
101
102       if (tv.tv_sec == 0 && tv.tv_usec == 0)
103          bored = 1;
104
105       /* Check and handle events on our local file descriptors
106        */
107       if (FD_ISSET( 0, &rfds )) {
108          /* Something on stdin */        
109          assert(rbuf_count == 0);
110          r = read(0, rbuf, BUFSZ);       
111          if (r < 1) {
112             perror("read");     
113             abort();
114          }
115          rbuf_count = r;
116       }
117
118       if (FD_ISSET( 1, &wfds )) {
119          /* Can write to stdout */
120          assert(rbuf_count > 0);
121          r = write(1, rbuf, rbuf_count);         
122          if (r < 1) {
123             perror("write");
124             abort();
125          }
126          rbuf_count -= r;
127          if (rbuf_count) 
128             memmove(rbuf + r, rbuf, rbuf_count);
129       }
130
131
132       /* Check and handle events generated by miniglx:
133        */
134       while (XCheckMaskEvent( dpy, ~0, &ev )) {
135          struct client *c;
136          bored = 0;
137
138          fprintf(stderr, "Received event %d\n", ev.type);
139
140          switch (ev.type) {
141          case CreateNotify: 
142             fprintf(stderr, "CreateNotify -- new client\n");
143             c = malloc(sizeof(*c));
144             c->next = clients;
145             c->windowid = ev.xcreatewindow.window;
146             c->mappable = False;
147             clients = c;
148             break;
149
150          case DestroyNotify:
151             fprintf(stderr, "DestroyNotify\n");
152             c = find_client(ev.xdestroywindow.window);
153             if (!c) break;
154             if (c == clients)
155                clients = c->next;
156             else {
157                struct client *t;
158                for (t = clients ; t->next != c ; t = t->next)
159                   ;
160                t->next = c->next;
161             }
162
163             if (c == mapped_client) 
164                mapped_client = 0;
165
166             free(c);
167             break;
168
169          case MapRequest:
170             fprintf(stderr, "MapRequest\n");
171             c = find_client(ev.xmaprequest.window);
172             if (!c) break;
173             c->mappable = True;
174             break;
175
176          case UnmapNotify:
177             fprintf(stderr, "UnmapNotify\n");
178             c = find_client(ev.xunmap.window);
179             if (!c) break;
180             c->mappable = False;
181             if (c == mapped_client)
182                mapped_client = 0;
183             break;
184
185          default:
186             break;
187          }
188       }
189
190
191       /* Search for first mappable client if none already mapped.
192        */
193       if (!mapped_client) {
194          struct client *c;
195          for (c = clients ; c ; c = c->next) {
196             if (c->mappable) {
197                XMapWindow( dpy, c->windowid );
198                mapped_client = c;
199                break;
200             }
201          }
202          if (!clients && autostart) {
203             system("nohup ./texline &");
204             system("nohup ./manytex &");
205          }
206       }
207       else if (bored) {
208          struct client *c;
209          /* bored of mapped client now, let's try & find another one */
210          for (c = mapped_client->next ; c && !c->mappable ; c = c->next)
211             ;
212          if (!c)
213             for (c = clients ; c && !c->mappable ; c = c->next)
214                ;
215          if (c && c != mapped_client) {
216             XUnmapWindow( dpy, mapped_client->windowid );
217             XMapWindow( dpy, c->windowid );
218             mapped_client = c;
219          }
220          else 
221             fprintf(stderr, "I'm bored!\n");
222       }
223    }
224
225    XCloseDisplay( dpy );
226
227    return 0;
228 }