sgl

annotate src/wsys_x11.c @ 13:e989ab58ec5b

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