rev |
line source |
nuclear@4
|
1 #include <stdlib.h>
|
nuclear@3
|
2 #include <X11/Xlib.h>
|
nuclear@3
|
3 #include <GL/glx.h>
|
nuclear@4
|
4 #include "sgl.h"
|
nuclear@3
|
5 #include "wsys.h"
|
nuclear@4
|
6 #include "log.h"
|
nuclear@3
|
7
|
nuclear@5
|
8
|
nuclear@3
|
9 struct window {
|
nuclear@3
|
10 Window win;
|
nuclear@3
|
11 GLXContext ctx;
|
nuclear@5
|
12 int width, height;
|
nuclear@5
|
13 int mapped;
|
nuclear@4
|
14 long evmask;
|
nuclear@5
|
15 int redisp_pending;
|
nuclear@3
|
16 struct window *next;
|
nuclear@3
|
17 };
|
nuclear@3
|
18
|
nuclear@3
|
19 static int init(void);
|
nuclear@3
|
20 static void shutdown(void);
|
nuclear@4
|
21
|
nuclear@4
|
22 /* video mode switching */
|
nuclear@4
|
23 static int set_vidmode(int xsz, int ysz);
|
nuclear@4
|
24 static int get_vidmode(int *xsz, int *ysz);
|
nuclear@4
|
25
|
nuclear@4
|
26 /* create/destroy windows */
|
nuclear@3
|
27 static int create_window(int xsz, int ysz, unsigned int flags);
|
nuclear@4
|
28 static void fill_attr(int *attr, unsigned int flags);
|
nuclear@4
|
29 static void print_visual_info(XVisualInfo *vis);
|
nuclear@3
|
30 static void close_window(int id);
|
nuclear@3
|
31
|
nuclear@4
|
32 /* window management */
|
nuclear@4
|
33 static int set_active(int id);
|
nuclear@5
|
34 static struct window *find_window(int id);
|
nuclear@5
|
35 static int activate_window(struct window *win);
|
nuclear@4
|
36 static int set_title(const char *str);
|
nuclear@4
|
37 static void redisplay(void);
|
nuclear@4
|
38 static void swap_buffers(void);
|
nuclear@4
|
39
|
nuclear@4
|
40 /* event handling and friends */
|
nuclear@4
|
41 static void set_bits(long *mask, long bits);
|
nuclear@4
|
42 static void clear_bits(long *mask, long bits);
|
nuclear@4
|
43 static void set_event(int idx, int enable);
|
nuclear@4
|
44 static int process_events(void);
|
nuclear@5
|
45 static int handle_event(XEvent *xev);
|
nuclear@5
|
46 static int translate_keysym(KeySym sym);
|
nuclear@4
|
47
|
nuclear@3
|
48 static struct wsys_module ws = {
|
nuclear@3
|
49 "x11-glx", 0,
|
nuclear@3
|
50 init,
|
nuclear@3
|
51 shutdown,
|
nuclear@3
|
52 set_vidmode,
|
nuclear@3
|
53 get_vidmode,
|
nuclear@3
|
54 create_window,
|
nuclear@3
|
55 close_window,
|
nuclear@4
|
56 set_active,
|
nuclear@4
|
57 set_title,
|
nuclear@4
|
58 redisplay,
|
nuclear@4
|
59 swap_buffers,
|
nuclear@4
|
60 set_event,
|
nuclear@4
|
61 process_events,
|
nuclear@3
|
62 0
|
nuclear@3
|
63 };
|
nuclear@3
|
64
|
nuclear@3
|
65 static Display *dpy;
|
nuclear@4
|
66 static Window root;
|
nuclear@3
|
67 static int scr;
|
nuclear@4
|
68 static Atom xa_wm_prot, xa_wm_del_win;
|
nuclear@3
|
69 static struct window *winlist;
|
nuclear@5
|
70 static struct window *active_win, *prev_active;
|
nuclear@3
|
71
|
nuclear@4
|
72 /* this is the only exported function, everything else should be static */
|
nuclear@3
|
73 void sgl_register_x11(void)
|
nuclear@3
|
74 {
|
nuclear@3
|
75 sgl_register_module(&ws);
|
nuclear@3
|
76 }
|
nuclear@3
|
77
|
nuclear@3
|
78 static int init(void)
|
nuclear@3
|
79 {
|
nuclear@5
|
80 if(dpy) {
|
nuclear@5
|
81 sgl_log("warning: double init\n");
|
nuclear@5
|
82 return 0;
|
nuclear@5
|
83 }
|
nuclear@5
|
84
|
nuclear@3
|
85 winlist = 0;
|
nuclear@5
|
86 active_win = prev_active = 0;
|
nuclear@3
|
87
|
nuclear@3
|
88 if(!(dpy = XOpenDisplay(0))) {
|
nuclear@4
|
89 sgl_log("failed to open X display: %s\n", XDisplayName(0));
|
nuclear@3
|
90 return -1;
|
nuclear@3
|
91 }
|
nuclear@3
|
92 scr = DefaultScreen(dpy);
|
nuclear@4
|
93 root = RootWindow(dpy, scr);
|
nuclear@4
|
94
|
nuclear@4
|
95 xa_wm_prot = XInternAtom(dpy, "WM_PROTOCOLS", False);
|
nuclear@4
|
96 xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
nuclear@3
|
97
|
nuclear@3
|
98 return 0;
|
nuclear@3
|
99 }
|
nuclear@3
|
100
|
nuclear@3
|
101 static void shutdown(void)
|
nuclear@3
|
102 {
|
nuclear@5
|
103 if(!dpy) {
|
nuclear@5
|
104 return;
|
nuclear@5
|
105 }
|
nuclear@5
|
106
|
nuclear@3
|
107 while(winlist) {
|
nuclear@3
|
108 struct window *win = winlist;
|
nuclear@3
|
109 winlist = winlist->next;
|
nuclear@3
|
110
|
nuclear@3
|
111 glXDestroyContext(dpy, win->ctx);
|
nuclear@4
|
112 XDestroyWindow(dpy, win->win);
|
nuclear@3
|
113 free(win);
|
nuclear@3
|
114 }
|
nuclear@3
|
115 XCloseDisplay(dpy);
|
nuclear@3
|
116 dpy = 0;
|
nuclear@3
|
117 }
|
nuclear@3
|
118
|
nuclear@4
|
119 static int set_vidmode(int xsz, int ysz)
|
nuclear@3
|
120 {
|
nuclear@3
|
121 /* TODO */
|
nuclear@4
|
122 return 0;
|
nuclear@3
|
123 }
|
nuclear@3
|
124
|
nuclear@4
|
125 static int get_vidmode(int *xsz, int *ysz)
|
nuclear@3
|
126 {
|
nuclear@3
|
127 /* TODO */
|
nuclear@4
|
128 return 0;
|
nuclear@3
|
129 }
|
nuclear@3
|
130
|
nuclear@3
|
131 static int create_window(int xsz, int ysz, unsigned int flags)
|
nuclear@3
|
132 {
|
nuclear@4
|
133 int attr[32];
|
nuclear@4
|
134 Window win;
|
nuclear@4
|
135 GLXContext ctx;
|
nuclear@4
|
136 XVisualInfo *vis;
|
nuclear@4
|
137 XClassHint chint;
|
nuclear@4
|
138 XSetWindowAttributes xattr;
|
nuclear@4
|
139 unsigned int attr_valid;
|
nuclear@4
|
140 long evmask;
|
nuclear@4
|
141 struct window *wnode;
|
nuclear@4
|
142
|
nuclear@4
|
143 if(!(wnode = malloc(sizeof *wnode))) {
|
nuclear@4
|
144 return -1;
|
nuclear@4
|
145 }
|
nuclear@4
|
146
|
nuclear@4
|
147 fill_attr(attr, flags);
|
nuclear@4
|
148
|
nuclear@4
|
149 if(!(vis = glXChooseVisual(dpy, scr, attr))) {
|
nuclear@4
|
150 sgl_log("failed to find a suitable visual\n");
|
nuclear@4
|
151 free(wnode);
|
nuclear@4
|
152 return -1;
|
nuclear@4
|
153 }
|
nuclear@4
|
154 print_visual_info(vis);
|
nuclear@4
|
155
|
nuclear@4
|
156 if(!(ctx = glXCreateContext(dpy, vis, 0, True))) {
|
nuclear@4
|
157 sgl_log("failed to create OpenGL context\n");
|
nuclear@4
|
158 XFree(vis);
|
nuclear@4
|
159 free(wnode);
|
nuclear@4
|
160 return -1;
|
nuclear@4
|
161 }
|
nuclear@4
|
162
|
nuclear@4
|
163 xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, scr);
|
nuclear@4
|
164 xattr.colormap = XCreateColormap(dpy, root, vis->visual, AllocNone);
|
nuclear@4
|
165 attr_valid = CWColormap | CWBackPixel | CWBorderPixel;
|
nuclear@4
|
166
|
nuclear@4
|
167 if(!(win = XCreateWindow(dpy, root, 0, 0, xsz, ysz, 0, vis->depth, InputOutput,
|
nuclear@4
|
168 vis->visual, attr_valid, &xattr))) {
|
nuclear@4
|
169 sgl_log("failed to create window\n");
|
nuclear@4
|
170 glXDestroyContext(dpy, ctx);
|
nuclear@4
|
171 XFree(vis);
|
nuclear@4
|
172 free(wnode);
|
nuclear@4
|
173 return -1;
|
nuclear@4
|
174 }
|
nuclear@4
|
175 XFree(vis);
|
nuclear@4
|
176
|
nuclear@4
|
177 evmask = StructureNotifyMask | VisibilityChangeMask;
|
nuclear@4
|
178 XSelectInput(dpy, win, evmask);
|
nuclear@4
|
179
|
nuclear@4
|
180 XSetWMProtocols(dpy, win, &xa_wm_del_win, 1);
|
nuclear@4
|
181
|
nuclear@4
|
182 set_title("OpenGL/X11");
|
nuclear@4
|
183
|
nuclear@4
|
184 chint.res_name = chint.res_class = "simplygl";
|
nuclear@4
|
185 XSetClassHint(dpy, win, &chint);
|
nuclear@4
|
186
|
nuclear@4
|
187 XMapWindow(dpy, win);
|
nuclear@4
|
188
|
nuclear@4
|
189 wnode->win = win;
|
nuclear@4
|
190 wnode->ctx = ctx;
|
nuclear@5
|
191 wnode->width = xsz;
|
nuclear@5
|
192 wnode->height = ysz;
|
nuclear@5
|
193 wnode->mapped = 0;
|
nuclear@4
|
194 wnode->evmask = evmask;
|
nuclear@5
|
195 wnode->redisp_pending = 1;
|
nuclear@4
|
196 wnode->next = winlist;
|
nuclear@5
|
197 winlist = wnode;
|
nuclear@4
|
198
|
nuclear@4
|
199 if(!active_win) {
|
nuclear@4
|
200 set_active(win);
|
nuclear@4
|
201 }
|
nuclear@4
|
202 return win;
|
nuclear@4
|
203 }
|
nuclear@4
|
204
|
nuclear@4
|
205 static void fill_attr(int *attr, unsigned int flags)
|
nuclear@4
|
206 {
|
nuclear@4
|
207 int i = 0;
|
nuclear@4
|
208
|
nuclear@4
|
209 attr[i++] = GLX_RGBA;
|
nuclear@4
|
210 attr[i++] = GLX_RED_SIZE; attr[i++] = 1;
|
nuclear@4
|
211 attr[i++] = GLX_GREEN_SIZE; attr[i++] = 1;
|
nuclear@4
|
212 attr[i++] = GLX_BLUE_SIZE; attr[i++] = 1;
|
nuclear@4
|
213
|
nuclear@4
|
214 if(flags & SGL_DOUBLE) {
|
nuclear@4
|
215 attr[i++] = GLX_DOUBLEBUFFER;
|
nuclear@4
|
216 }
|
nuclear@4
|
217 if(flags & SGL_DEPTH) {
|
nuclear@4
|
218 attr[i++] = GLX_DEPTH_SIZE;
|
nuclear@4
|
219 attr[i++] = 1;
|
nuclear@4
|
220 }
|
nuclear@4
|
221 if(flags & SGL_STENCIL) {
|
nuclear@4
|
222 attr[i++] = GLX_STENCIL_SIZE;
|
nuclear@4
|
223 attr[i++] = 1;
|
nuclear@4
|
224 }
|
nuclear@4
|
225 if(flags & SGL_STEREO) {
|
nuclear@4
|
226 attr[i++] = GLX_STEREO;
|
nuclear@4
|
227 }
|
nuclear@4
|
228 #if defined(GLX_VERSION_1_4) || defined(GLX_ARB_multisample)
|
nuclear@4
|
229 if(flags & SGL_MULTISAMPLE) {
|
nuclear@4
|
230 attr[i++] = GLX_SAMPLE_BUFFERS_ARB;
|
nuclear@4
|
231 attr[i++] = 1;
|
nuclear@4
|
232 attr[i++] = GLX_SAMPLES_ARB;
|
nuclear@4
|
233 attr[i++] = 1;
|
nuclear@4
|
234 }
|
nuclear@4
|
235 #endif /* defined GLX_VERSION_1_4 || GLX_ARB_multisample */
|
nuclear@4
|
236 attr[i] = None;
|
nuclear@4
|
237 }
|
nuclear@4
|
238
|
nuclear@4
|
239 static void print_visual_info(XVisualInfo *vis)
|
nuclear@4
|
240 {
|
nuclear@4
|
241 int rbits, gbits, bbits, zbits, sbits, stereo, aa, samples;
|
nuclear@4
|
242
|
nuclear@4
|
243 glXGetConfig(dpy, vis, GLX_RED_SIZE, &rbits);
|
nuclear@4
|
244 glXGetConfig(dpy, vis, GLX_GREEN_SIZE, &gbits);
|
nuclear@4
|
245 glXGetConfig(dpy, vis, GLX_BLUE_SIZE, &bbits);
|
nuclear@4
|
246 glXGetConfig(dpy, vis, GLX_DEPTH_SIZE, &zbits);
|
nuclear@4
|
247 glXGetConfig(dpy, vis, GLX_STENCIL_SIZE, &sbits);
|
nuclear@4
|
248 glXGetConfig(dpy, vis, GLX_STEREO, &stereo);
|
nuclear@4
|
249 #if defined(GLX_VERSION_1_4) || defined(GLX_ARB_multisample)
|
nuclear@4
|
250 glXGetConfig(dpy, vis, GLX_SAMPLE_BUFFERS_ARB, &aa);
|
nuclear@4
|
251 if(aa) {
|
nuclear@4
|
252 glXGetConfig(dpy, vis, GLX_SAMPLES_ARB, &samples);
|
nuclear@4
|
253 } else {
|
nuclear@4
|
254 samples = 1;
|
nuclear@4
|
255 }
|
nuclear@4
|
256 #endif /* defined GLX_VERSION_1_4 || GLX_ARB_multisample */
|
nuclear@4
|
257
|
nuclear@4
|
258 sgl_log("got visual: %d%d%d d:%d s:%d", rbits, gbits, bbits, zbits, sbits);
|
nuclear@4
|
259 sgl_log(" %s", stereo ? "stereo" : "mono");
|
nuclear@4
|
260 sgl_log(" samples/pixel: %d\n", samples);
|
nuclear@3
|
261 }
|
nuclear@3
|
262
|
nuclear@3
|
263 static void close_window(int id)
|
nuclear@3
|
264 {
|
nuclear@3
|
265 struct window dummy, *win, *prev;
|
nuclear@3
|
266 dummy.next = winlist;
|
nuclear@3
|
267
|
nuclear@3
|
268 prev = &dummy;
|
nuclear@3
|
269 win = prev->next;
|
nuclear@3
|
270
|
nuclear@3
|
271 while(win) {
|
nuclear@3
|
272 if(win->win == id) {
|
nuclear@3
|
273 glXDestroyContext(dpy, win->ctx);
|
nuclear@4
|
274 XDestroyWindow(dpy, win->win);
|
nuclear@3
|
275 prev->next = win->next;
|
nuclear@3
|
276 free(win);
|
nuclear@3
|
277 return;
|
nuclear@3
|
278 }
|
nuclear@3
|
279 win = win->next;
|
nuclear@3
|
280 }
|
nuclear@3
|
281 }
|
nuclear@4
|
282
|
nuclear@4
|
283 static int set_active(int id)
|
nuclear@4
|
284 {
|
nuclear@5
|
285 struct window *win = find_window(id);
|
nuclear@5
|
286 if(!win) {
|
nuclear@5
|
287 sgl_log("no such window: %d\n", id);
|
nuclear@5
|
288 return -1;
|
nuclear@5
|
289 }
|
nuclear@5
|
290 /* only the user calls this, so don't revert this selection */
|
nuclear@5
|
291 prev_active = win;
|
nuclear@5
|
292 return activate_window(win);
|
nuclear@5
|
293 }
|
nuclear@5
|
294
|
nuclear@5
|
295 static struct window *find_window(int id)
|
nuclear@5
|
296 {
|
nuclear@4
|
297 struct window *win = winlist;
|
nuclear@4
|
298
|
nuclear@4
|
299 while(win) {
|
nuclear@4
|
300 if(win->win == id) {
|
nuclear@5
|
301 return win;
|
nuclear@4
|
302 }
|
nuclear@4
|
303 win = win->next;
|
nuclear@4
|
304 }
|
nuclear@5
|
305 return 0;
|
nuclear@5
|
306 }
|
nuclear@4
|
307
|
nuclear@5
|
308 static int activate_window(struct window *win)
|
nuclear@5
|
309 {
|
nuclear@5
|
310 if(glXMakeCurrent(dpy, win->win, win->ctx) == False) {
|
nuclear@5
|
311 sgl_log("failed to activate window %d\n", (int)win->win);
|
nuclear@5
|
312 return -1;
|
nuclear@5
|
313 }
|
nuclear@5
|
314 active_win = win;
|
nuclear@5
|
315 return 0;
|
nuclear@4
|
316 }
|
nuclear@4
|
317
|
nuclear@4
|
318 static int set_title(const char *str)
|
nuclear@4
|
319 {
|
nuclear@4
|
320 XTextProperty wm_name;
|
nuclear@4
|
321
|
nuclear@4
|
322 if(!str || !active_win) {
|
nuclear@4
|
323 return -1;
|
nuclear@4
|
324 }
|
nuclear@4
|
325 XStringListToTextProperty((char**)&str, 1, &wm_name);
|
nuclear@4
|
326 XSetWMName(dpy, active_win->win, &wm_name);
|
nuclear@4
|
327 XSetWMIconName(dpy, active_win->win, &wm_name);
|
nuclear@4
|
328 XFree(wm_name.value);
|
nuclear@4
|
329 return 0;
|
nuclear@4
|
330 }
|
nuclear@4
|
331
|
nuclear@4
|
332 static void redisplay(void)
|
nuclear@4
|
333 {
|
nuclear@4
|
334 active_win->redisp_pending = 1;
|
nuclear@4
|
335 }
|
nuclear@4
|
336
|
nuclear@4
|
337 static void swap_buffers(void)
|
nuclear@4
|
338 {
|
nuclear@5
|
339 glXSwapBuffers(dpy, active_win->win);
|
nuclear@4
|
340 }
|
nuclear@4
|
341
|
nuclear@4
|
342 static void set_bits(long *mask, long bits)
|
nuclear@4
|
343 {
|
nuclear@4
|
344 *mask |= bits;
|
nuclear@4
|
345 }
|
nuclear@4
|
346
|
nuclear@4
|
347 static void clear_bits(long *mask, long bits)
|
nuclear@4
|
348 {
|
nuclear@4
|
349 *mask &= ~bits;
|
nuclear@4
|
350 }
|
nuclear@4
|
351
|
nuclear@4
|
352 static void set_event(int idx, int enable)
|
nuclear@4
|
353 {
|
nuclear@4
|
354 void (*op)(long*, long);
|
nuclear@4
|
355 op = enable ? set_bits : clear_bits;
|
nuclear@4
|
356
|
nuclear@4
|
357 switch(idx) {
|
nuclear@4
|
358 case SGL_DISPLAY:
|
nuclear@4
|
359 op(&active_win->evmask, ExposureMask);
|
nuclear@4
|
360 break;
|
nuclear@4
|
361
|
nuclear@4
|
362 case SGL_KEYBOARD:
|
nuclear@4
|
363 op(&active_win->evmask, KeyPressMask | KeyReleaseMask);
|
nuclear@4
|
364 break;
|
nuclear@4
|
365
|
nuclear@4
|
366 case SGL_MOUSE:
|
nuclear@4
|
367 op(&active_win->evmask, ButtonPressMask | ButtonReleaseMask);
|
nuclear@4
|
368 break;
|
nuclear@4
|
369
|
nuclear@4
|
370 case SGL_MOTION:
|
nuclear@4
|
371 op(&active_win->evmask, ButtonMotionMask);
|
nuclear@4
|
372 break;
|
nuclear@4
|
373
|
nuclear@4
|
374 case SGL_PASSIVE:
|
nuclear@4
|
375 op(&active_win->evmask, PointerMotionMask);
|
nuclear@4
|
376 break;
|
nuclear@4
|
377
|
nuclear@4
|
378 default:
|
nuclear@4
|
379 return;
|
nuclear@4
|
380 }
|
nuclear@4
|
381
|
nuclear@4
|
382 XSelectInput(dpy, active_win->win, active_win->evmask);
|
nuclear@4
|
383 }
|
nuclear@4
|
384
|
nuclear@4
|
385 static int process_events(void)
|
nuclear@4
|
386 {
|
nuclear@4
|
387 XEvent xev;
|
nuclear@4
|
388 void (*func)();
|
nuclear@5
|
389 struct window *win;
|
nuclear@4
|
390
|
nuclear@5
|
391 prev_active = active_win;
|
nuclear@5
|
392
|
nuclear@5
|
393 win = winlist;
|
nuclear@5
|
394 while(win) {
|
nuclear@5
|
395 if(win->redisp_pending && (func = sgl_get_callback(SGL_DISPLAY))) {
|
nuclear@5
|
396 activate_window(win);
|
nuclear@5
|
397 func();
|
nuclear@5
|
398 win->redisp_pending = 0;
|
nuclear@5
|
399 }
|
nuclear@5
|
400 win = win->next;
|
nuclear@5
|
401 }
|
nuclear@5
|
402
|
nuclear@5
|
403 func = sgl_get_callback(SGL_IDLE);
|
nuclear@5
|
404 if(!func) {
|
nuclear@5
|
405 XNextEvent(dpy, &xev);
|
nuclear@5
|
406 XPutBackEvent(dpy, &xev);
|
nuclear@5
|
407 }
|
nuclear@5
|
408
|
nuclear@5
|
409 /* process all pending events... */
|
nuclear@4
|
410 while(XPending(dpy)) {
|
nuclear@4
|
411 XNextEvent(dpy, &xev);
|
nuclear@5
|
412 if(handle_event(&xev) == -1) {
|
nuclear@5
|
413 return -1;
|
nuclear@5
|
414 }
|
nuclear@4
|
415
|
nuclear@5
|
416 if(!dpy) {
|
nuclear@5
|
417 return -1;
|
nuclear@5
|
418 }
|
nuclear@5
|
419 }
|
nuclear@5
|
420
|
nuclear@5
|
421 if(func) {
|
nuclear@5
|
422 /* ... and then call the idle function */
|
nuclear@5
|
423 func();
|
nuclear@5
|
424 }
|
nuclear@5
|
425
|
nuclear@5
|
426 activate_window(prev_active);
|
nuclear@5
|
427 return 0;
|
nuclear@5
|
428 }
|
nuclear@5
|
429
|
nuclear@5
|
430 /* returns 0, or -1 when the last window gets closed */
|
nuclear@5
|
431 static int handle_event(XEvent *xev)
|
nuclear@5
|
432 {
|
nuclear@5
|
433 int state;
|
nuclear@5
|
434 struct window *win;
|
nuclear@5
|
435 void (*func)();
|
nuclear@5
|
436
|
nuclear@5
|
437 if((win = find_window(xev->xany.window))) {
|
nuclear@5
|
438 activate_window(win);
|
nuclear@5
|
439 } else {
|
nuclear@5
|
440 return 0;
|
nuclear@5
|
441 }
|
nuclear@5
|
442
|
nuclear@5
|
443 switch(xev->type) {
|
nuclear@5
|
444 case MapNotify:
|
nuclear@5
|
445 active_win->mapped = 1;
|
nuclear@5
|
446 break;
|
nuclear@5
|
447
|
nuclear@5
|
448 case UnmapNotify:
|
nuclear@5
|
449 active_win->mapped = 0;
|
nuclear@5
|
450 break;
|
nuclear@5
|
451
|
nuclear@5
|
452 case Expose:
|
nuclear@5
|
453 if(active_win->mapped && xev->xexpose.count == 0) {
|
nuclear@5
|
454 if((func = sgl_get_callback(SGL_DISPLAY))) {
|
nuclear@5
|
455 func();
|
nuclear@5
|
456 active_win->redisp_pending = 0;
|
nuclear@5
|
457 }
|
nuclear@5
|
458 }
|
nuclear@5
|
459 break;
|
nuclear@5
|
460
|
nuclear@5
|
461 case MotionNotify:
|
nuclear@5
|
462 if(xev->xmotion.state) {
|
nuclear@5
|
463 func = sgl_get_callback(SGL_MOTION);
|
nuclear@5
|
464 } else {
|
nuclear@5
|
465 func = sgl_get_callback(SGL_PASSIVE);
|
nuclear@5
|
466 }
|
nuclear@5
|
467 if(func) {
|
nuclear@5
|
468 func(xev->xmotion.x, xev->xmotion.y);
|
nuclear@5
|
469 }
|
nuclear@5
|
470 break;
|
nuclear@5
|
471
|
nuclear@5
|
472 case ButtonPress:
|
nuclear@5
|
473 if(1) {
|
nuclear@5
|
474 state = 1;
|
nuclear@5
|
475 } else {
|
nuclear@5
|
476 case ButtonRelease:
|
nuclear@5
|
477 state = 0;
|
nuclear@5
|
478 }
|
nuclear@5
|
479 if((func = sgl_get_callback(SGL_MOUSE))) {
|
nuclear@5
|
480 int bn = xev->xbutton.button - 1;
|
nuclear@5
|
481 func(bn, state, xev->xbutton.x, xev->xbutton.y);
|
nuclear@5
|
482 }
|
nuclear@5
|
483 break;
|
nuclear@5
|
484
|
nuclear@5
|
485 case KeyPress:
|
nuclear@5
|
486 if(1) {
|
nuclear@5
|
487 state = 1;
|
nuclear@5
|
488 } else {
|
nuclear@5
|
489 case KeyRelease:
|
nuclear@5
|
490 state = 0;
|
nuclear@5
|
491 }
|
nuclear@5
|
492 if((func = sgl_get_callback(SGL_KEYBOARD))) {
|
nuclear@5
|
493 KeySym sym = XLookupKeysym(&xev->xkey, 0);
|
nuclear@5
|
494 func(translate_keysym(sym), state);
|
nuclear@5
|
495 }
|
nuclear@5
|
496 break;
|
nuclear@5
|
497
|
nuclear@5
|
498 case ConfigureNotify:
|
nuclear@5
|
499 if((func = sgl_get_callback(SGL_RESHAPE))) {
|
nuclear@5
|
500 if(xev->xconfigure.width != active_win->width || xev->xconfigure.height != active_win->height) {
|
nuclear@5
|
501 active_win->width = xev->xconfigure.width;
|
nuclear@5
|
502 active_win->height = xev->xconfigure.height;
|
nuclear@5
|
503
|
nuclear@5
|
504 func(xev->xconfigure.width, xev->xconfigure.height);
|
nuclear@5
|
505 }
|
nuclear@5
|
506 }
|
nuclear@5
|
507 break;
|
nuclear@5
|
508
|
nuclear@5
|
509 case ClientMessage:
|
nuclear@5
|
510 if(xev->xclient.message_type == xa_wm_prot) {
|
nuclear@5
|
511 if(xev->xclient.data.l[0] == xa_wm_del_win) {
|
nuclear@5
|
512 close_window(active_win->win);
|
nuclear@5
|
513 if(!active_win) {
|
nuclear@5
|
514 return -1;
|
nuclear@4
|
515 }
|
nuclear@4
|
516 }
|
nuclear@5
|
517 }
|
nuclear@5
|
518 break;
|
nuclear@4
|
519
|
nuclear@5
|
520 default:
|
nuclear@5
|
521 break;
|
nuclear@5
|
522 }
|
nuclear@4
|
523
|
nuclear@4
|
524 return 0;
|
nuclear@4
|
525 }
|
nuclear@5
|
526
|
nuclear@5
|
527 static int translate_keysym(KeySym sym)
|
nuclear@5
|
528 {
|
nuclear@5
|
529 if(sym < 256) {
|
nuclear@5
|
530 return sym;
|
nuclear@5
|
531 }
|
nuclear@5
|
532
|
nuclear@5
|
533 switch(sym) {
|
nuclear@5
|
534 case XK_BackSpace:
|
nuclear@5
|
535 return '\b';
|
nuclear@5
|
536 case XK_Tab:
|
nuclear@5
|
537 return '\t';
|
nuclear@5
|
538 case XK_Linefeed:
|
nuclear@5
|
539 return '\r';
|
nuclear@5
|
540 case XK_Return:
|
nuclear@5
|
541 return '\n';
|
nuclear@5
|
542 case XK_Escape:
|
nuclear@5
|
543 return 27;
|
nuclear@5
|
544 default:
|
nuclear@5
|
545 break;
|
nuclear@5
|
546 }
|
nuclear@5
|
547 return (int)sym;
|
nuclear@5
|
548 }
|