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