sgl

changeset 4:648f8604d2b2

cont. x11 module
author John Tsiombikas <nuclear@siggraph.org>
date Thu, 12 May 2011 11:04:10 +0300
parents 1b6c5dadb460
children 0570e27e5ebc
files include/sgl.h src/cb.c src/log.c src/log.h src/sgl.c src/wsys.h src/wsys_x11.c
diffstat 7 files changed, 447 insertions(+), 24 deletions(-) [+]
line diff
     1.1 --- a/include/sgl.h	Wed May 11 09:09:43 2011 +0300
     1.2 +++ b/include/sgl.h	Thu May 12 11:04:10 2011 +0300
     1.3 @@ -5,6 +5,7 @@
     1.4  #define SGL_DEPTH		2
     1.5  #define SGL_STENCIL		4
     1.6  #define SGL_STEREO		8
     1.7 +#define SGL_MULTISAMPLE	16
     1.8  
     1.9  enum {
    1.10  	SGL_CREATE,
    1.11 @@ -23,15 +24,22 @@
    1.12  int sgl_init(void);
    1.13  void sgl_shutdown(void);
    1.14  
    1.15 -int sgl_set_video_mode(int xsz, int ysz, int bpp);
    1.16 -int sgl_get_video_mode(int *xsz, int *ysz, int *bpp);
    1.17 +int sgl_set_video_mode(int xsz, int ysz);
    1.18 +int sgl_get_video_mode(int *xsz, int *ysz);
    1.19  
    1.20 -int sgl_window(int xsz, int ysz, unsigned int mode);
    1.21 +int sgl_create_window(int xsz, int ysz, unsigned int mode);
    1.22  void sgl_close_window(int win);
    1.23  
    1.24 +int sgl_set_active(int id);
    1.25 +int sgl_set_title(const char *str);
    1.26 +
    1.27 +int sgl_process_events(void);
    1.28 +int sgl_event_loop(void);
    1.29 +
    1.30  int sgl_push_callbacks(void);
    1.31  int sgl_pop_callbacks(void);
    1.32  void sgl_clear_callbacks(void);
    1.33 -void (*sgl_callback(int idx, void (*func)()))();
    1.34 +void sgl_set_callback(int idx, void (*func)());
    1.35 +void (*sgl_get_callback(int idx))();
    1.36  
    1.37  #endif	/* SGL_H_ */
     2.1 --- a/src/cb.c	Wed May 11 09:09:43 2011 +0300
     2.2 +++ b/src/cb.c	Thu May 12 11:04:10 2011 +0300
     2.3 @@ -1,12 +1,15 @@
     2.4  #include <stdlib.h>
     2.5  #include <string.h>
     2.6  #include "sgl.h"
     2.7 +#include "wsys.h"
     2.8  
     2.9  struct cbnode {
    2.10  	void (*func[SGL_NUM_CALLBACKS])();
    2.11  	struct cbnode *next;
    2.12  };
    2.13  
    2.14 +static void notify_wsys(void);
    2.15 +
    2.16  struct cbnode first_cbnode;
    2.17  struct cbnode *cb = &first_cbnode;
    2.18  
    2.19 @@ -34,17 +37,36 @@
    2.20  	node = cb;
    2.21  	cb = cb->next;
    2.22  	free(node);
    2.23 +
    2.24 +	notify_wsys();
    2.25  	return 0;
    2.26  }
    2.27  
    2.28  void sgl_clear_callbacks(void)
    2.29  {
    2.30  	memset(cb->func, 0, sizeof cb->func);
    2.31 +	notify_wsys();
    2.32  }
    2.33  
    2.34 -void (*sgl_callback(int idx, void (*func)()))()
    2.35 +void sgl_callback(int idx, void (*func)())
    2.36  {
    2.37 -	void (*prev)() = cb->func[idx];
    2.38  	cb->func[idx] = func;
    2.39 -	return prev;
    2.40  }
    2.41 +
    2.42 +void (*sgl_get_callback(int idx))()
    2.43 +{
    2.44 +	return cb->func[idx];
    2.45 +}
    2.46 +
    2.47 +/* notify the window system module as to which events are active */
    2.48 +static void notify_wsys(void)
    2.49 +{
    2.50 +	int i;
    2.51 +	struct wsys_module *ws;
    2.52 +
    2.53 +	if((ws = sgl_wsys_module())) {
    2.54 +		for(i=0; i<SGL_NUM_CALLBACKS; i++) {
    2.55 +			ws->set_event(i, cb->func[i] != 0);
    2.56 +		}
    2.57 +	}
    2.58 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/log.c	Thu May 12 11:04:10 2011 +0300
     3.3 @@ -0,0 +1,21 @@
     3.4 +#include <stdio.h>
     3.5 +#include <stdlib.h>
     3.6 +#include <stdarg.h>
     3.7 +#include "log.h"
     3.8 +
     3.9 +void sgl_log(const char *fmt, ...)
    3.10 +{
    3.11 +	va_list ap;
    3.12 +	const char *logfile;
    3.13 +	FILE *fp;
    3.14 +
    3.15 +	if(!(logfile = getenv("SGL_LOG")) || !(fp = fopen(logfile, "a"))) {
    3.16 +		fp = stderr;
    3.17 +	}
    3.18 +
    3.19 +	va_start(ap, fmt);
    3.20 +	vfprintf(fp, fmt, ap);
    3.21 +	va_end(ap);
    3.22 +
    3.23 +	fclose(fp);
    3.24 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/log.h	Thu May 12 11:04:10 2011 +0300
     4.3 @@ -0,0 +1,6 @@
     4.4 +#ifndef LOG_H_
     4.5 +#define LOG_H_
     4.6 +
     4.7 +void sgl_log(const char *fmt, ...);
     4.8 +
     4.9 +#endif	/* LOG_H_ */
     5.1 --- a/src/sgl.c	Wed May 11 09:09:43 2011 +0300
     5.2 +++ b/src/sgl.c	Thu May 12 11:04:10 2011 +0300
     5.3 @@ -1,29 +1,57 @@
     5.4  #include "sgl.h"
     5.5 +#include "wsys.h"
     5.6  
     5.7  void sgl_register_modules(void);
     5.8  
     5.9 +static struct wsys_module *ws;
    5.10 +
    5.11  int sgl_init(void)
    5.12  {
    5.13  	sgl_register_modules();
    5.14  	sgl_sort_modules();
    5.15 -	return 0;
    5.16 +
    5.17 +	if(!(ws = sgl_wsys_module())) {
    5.18 +		return -1;
    5.19 +	}
    5.20 +	return ws->init();
    5.21  }
    5.22  
    5.23 -int sgl_set_video_mode(int xsz, int ysz, int bpp)
    5.24 +void sgl_shutdown(void)
    5.25  {
    5.26 -	return 0;
    5.27 +	ws->shutdown();
    5.28  }
    5.29  
    5.30 -int sgl_get_video_mode(int *xsz, int *ysz, int *bpp)
    5.31 +int sgl_set_video_mode(int xsz, int ysz)
    5.32  {
    5.33 -	return 0;
    5.34 +	return ws->set_vidmode(xsz, ysz);
    5.35  }
    5.36  
    5.37 -int sgl_window(int x, int y, unsigned int mode)
    5.38 +int sgl_get_video_mode(int *xsz, int *ysz)
    5.39  {
    5.40 -	return 0;
    5.41 +	return ws->get_vidmode(xsz, ysz);
    5.42  }
    5.43  
    5.44 -void sgl_close(int win)
    5.45 +int sgl_create_window(int xsz, int ysz, unsigned int mode)
    5.46  {
    5.47 +	return ws->create_window(xsz, ysz, mode);
    5.48  }
    5.49 +
    5.50 +void sgl_close_window(int win)
    5.51 +{
    5.52 +	ws->close_window(win);
    5.53 +}
    5.54 +
    5.55 +int sgl_set_active(int id)
    5.56 +{
    5.57 +	return ws->set_active(id);
    5.58 +}
    5.59 +
    5.60 +int sgl_set_title(const char *str)
    5.61 +{
    5.62 +	return ws->set_title(str);
    5.63 +}
    5.64 +
    5.65 +int sgl_process_events(void)
    5.66 +{
    5.67 +	return ws->process_events();
    5.68 +}
     6.1 --- a/src/wsys.h	Wed May 11 09:09:43 2011 +0300
     6.2 +++ b/src/wsys.h	Thu May 12 11:04:10 2011 +0300
     6.3 @@ -8,11 +8,21 @@
     6.4  	int (*init)(void);
     6.5  	void (*shutdown)(void);
     6.6  
     6.7 -	int (*set_vidmode)(int, int, int);
     6.8 -	int (*get_vidmode)(int*, int*, int*);
     6.9 +	int (*set_vidmode)(int, int);
    6.10 +	int (*get_vidmode)(int*, int*);
    6.11 +
    6.12  	int (*create_window)(int, int, unsigned int);
    6.13  	void (*close_window)(int);
    6.14  
    6.15 +	int (*set_active)(int);
    6.16 +	int (*set_title)(const char*);
    6.17 +
    6.18 +	void (*set_event)(int idx, int enable);
    6.19 +	int (*process_events)(void);
    6.20 +
    6.21 +	void (*redisplay)(void);
    6.22 +	void (*swap_buffers)(void);
    6.23 +
    6.24  	struct wsys_module *next;
    6.25  };
    6.26  
     7.1 --- a/src/wsys_x11.c	Wed May 11 09:09:43 2011 +0300
     7.2 +++ b/src/wsys_x11.c	Thu May 12 11:04:10 2011 +0300
     7.3 @@ -1,20 +1,43 @@
     7.4 +#include <stdlib.h>
     7.5  #include <X11/Xlib.h>
     7.6  #include <GL/glx.h>
     7.7 +#include "sgl.h"
     7.8  #include "wsys.h"
     7.9 +#include "log.h"
    7.10  
    7.11  struct window {
    7.12  	Window win;
    7.13  	GLXContext ctx;
    7.14 +	long evmask;
    7.15  	struct window *next;
    7.16  };
    7.17  
    7.18  static int init(void);
    7.19  static void shutdown(void);
    7.20 -static int set_vidmode(int xsz, int ysz, int bpp);
    7.21 -static int get_vidmode(int *xsz, int *ysz, int *bpp);
    7.22 +
    7.23 +/* video mode switching */
    7.24 +static int set_vidmode(int xsz, int ysz);
    7.25 +static int get_vidmode(int *xsz, int *ysz);
    7.26 +
    7.27 +/* create/destroy windows */
    7.28  static int create_window(int xsz, int ysz, unsigned int flags);
    7.29 +static void fill_attr(int *attr, unsigned int flags);
    7.30 +static void print_visual_info(XVisualInfo *vis);
    7.31  static void close_window(int id);
    7.32  
    7.33 +/* window management */
    7.34 +static int set_active(int id);
    7.35 +static int set_title(const char *str);
    7.36 +static void redisplay(void);
    7.37 +static void swap_buffers(void);
    7.38 +
    7.39 +/* event handling and friends */
    7.40 +static void set_bits(long *mask, long bits);
    7.41 +static void clear_bits(long *mask, long bits);
    7.42 +static void set_event(int idx, int enable);
    7.43 +static int process_events(void);
    7.44 +
    7.45 +
    7.46  static struct wsys_module ws = {
    7.47  	"x11-glx", 0,
    7.48  	init,
    7.49 @@ -23,14 +46,23 @@
    7.50  	get_vidmode,
    7.51  	create_window,
    7.52  	close_window,
    7.53 +	set_active,
    7.54 +	set_title,
    7.55 +	redisplay,
    7.56 +	swap_buffers,
    7.57 +	set_event,
    7.58 +	process_events,
    7.59  	0
    7.60  };
    7.61  
    7.62  static Display *dpy;
    7.63 +static Window root;
    7.64  static int scr;
    7.65 +static Atom xa_wm_prot, xa_wm_del_win;
    7.66  static struct window *winlist;
    7.67 +static struct window *active_win;
    7.68  
    7.69 -
    7.70 +/* this is the only exported function, everything else should be static */
    7.71  void sgl_register_x11(void)
    7.72  {
    7.73  	sgl_register_module(&ws);
    7.74 @@ -41,9 +73,14 @@
    7.75  	winlist = 0;
    7.76  
    7.77  	if(!(dpy = XOpenDisplay(0))) {
    7.78 +		sgl_log("failed to open X display: %s\n", XDisplayName(0));
    7.79  		return -1;
    7.80  	}
    7.81  	scr = DefaultScreen(dpy);
    7.82 +	root = RootWindow(dpy, scr);
    7.83 +
    7.84 +	xa_wm_prot = XInternAtom(dpy, "WM_PROTOCOLS", False);
    7.85 +	xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
    7.86  
    7.87  	return 0;
    7.88  }
    7.89 @@ -55,25 +92,151 @@
    7.90  		winlist = winlist->next;
    7.91  
    7.92  		glXDestroyContext(dpy, win->ctx);
    7.93 -		XCloseWindow(dpy, win->win);
    7.94 +		XDestroyWindow(dpy, win->win);
    7.95  		free(win);
    7.96  	}
    7.97  	XCloseDisplay(dpy);
    7.98  	dpy = 0;
    7.99  }
   7.100  
   7.101 -static int set_vidmode(int xsz, int ysz, int bpp)
   7.102 +static int set_vidmode(int xsz, int ysz)
   7.103  {
   7.104  	/* TODO */
   7.105 +	return 0;
   7.106  }
   7.107  
   7.108 -static int get_vidmode(int *xsz, int *ysz, int *bpp)
   7.109 +static int get_vidmode(int *xsz, int *ysz)
   7.110  {
   7.111  	/* TODO */
   7.112 +	return 0;
   7.113  }
   7.114  
   7.115  static int create_window(int xsz, int ysz, unsigned int flags)
   7.116  {
   7.117 +	int attr[32];
   7.118 +	Window win;
   7.119 +	GLXContext ctx;
   7.120 +	XVisualInfo *vis;
   7.121 +	XClassHint chint;
   7.122 +	XSetWindowAttributes xattr;
   7.123 +	unsigned int attr_valid;
   7.124 +	long evmask;
   7.125 +	struct window *wnode;
   7.126 +
   7.127 +	if(!(wnode = malloc(sizeof *wnode))) {
   7.128 +		return -1;
   7.129 +	}
   7.130 +
   7.131 +	fill_attr(attr, flags);
   7.132 +
   7.133 +	if(!(vis = glXChooseVisual(dpy, scr, attr))) {
   7.134 +		sgl_log("failed to find a suitable visual\n");
   7.135 +		free(wnode);
   7.136 +		return -1;
   7.137 +	}
   7.138 +	print_visual_info(vis);
   7.139 +
   7.140 +	if(!(ctx = glXCreateContext(dpy, vis, 0, True))) {
   7.141 +		sgl_log("failed to create OpenGL context\n");
   7.142 +		XFree(vis);
   7.143 +		free(wnode);
   7.144 +		return -1;
   7.145 +	}
   7.146 +
   7.147 +	xattr.background_pixel = xattr.border_pixel = BlackPixel(dpy, scr);
   7.148 +	xattr.colormap = XCreateColormap(dpy, root, vis->visual, AllocNone);
   7.149 +	attr_valid = CWColormap | CWBackPixel | CWBorderPixel;
   7.150 +
   7.151 +	if(!(win = XCreateWindow(dpy, root, 0, 0, xsz, ysz, 0, vis->depth, InputOutput,
   7.152 +					vis->visual, attr_valid, &xattr))) {
   7.153 +		sgl_log("failed to create window\n");
   7.154 +		glXDestroyContext(dpy, ctx);
   7.155 +		XFree(vis);
   7.156 +		free(wnode);
   7.157 +		return -1;
   7.158 +	}
   7.159 +	XFree(vis);
   7.160 +
   7.161 +	evmask = StructureNotifyMask | VisibilityChangeMask;
   7.162 +	XSelectInput(dpy, win, evmask);
   7.163 +
   7.164 +	XSetWMProtocols(dpy, win, &xa_wm_del_win, 1);
   7.165 +
   7.166 +	set_title("OpenGL/X11");
   7.167 +
   7.168 +	chint.res_name = chint.res_class = "simplygl";
   7.169 +	XSetClassHint(dpy, win, &chint);
   7.170 +
   7.171 +	XMapWindow(dpy, win);
   7.172 +
   7.173 +	wnode->win = win;
   7.174 +	wnode->ctx = ctx;
   7.175 +	wnode->evmask = evmask;
   7.176 +	wnode->next = winlist;
   7.177 +	winlist->next = wnode;
   7.178 +
   7.179 +	if(!active_win) {
   7.180 +		set_active(win);
   7.181 +	}
   7.182 +	return win;
   7.183 +}
   7.184 +
   7.185 +static void fill_attr(int *attr, unsigned int flags)
   7.186 +{
   7.187 +	int i = 0;
   7.188 +
   7.189 +	attr[i++] = GLX_RGBA;
   7.190 +	attr[i++] = GLX_RED_SIZE; attr[i++] = 1;
   7.191 +	attr[i++] = GLX_GREEN_SIZE; attr[i++] = 1;
   7.192 +	attr[i++] = GLX_BLUE_SIZE; attr[i++] = 1;
   7.193 +
   7.194 +	if(flags & SGL_DOUBLE) {
   7.195 +		attr[i++] = GLX_DOUBLEBUFFER;
   7.196 +	}
   7.197 +	if(flags & SGL_DEPTH) {
   7.198 +		attr[i++] = GLX_DEPTH_SIZE;
   7.199 +		attr[i++] = 1;
   7.200 +	}
   7.201 +	if(flags & SGL_STENCIL) {
   7.202 +		attr[i++] = GLX_STENCIL_SIZE;
   7.203 +		attr[i++] = 1;
   7.204 +	}
   7.205 +	if(flags & SGL_STEREO) {
   7.206 +		attr[i++] = GLX_STEREO;
   7.207 +	}
   7.208 +#if defined(GLX_VERSION_1_4) || defined(GLX_ARB_multisample)
   7.209 +	if(flags & SGL_MULTISAMPLE) {
   7.210 +		attr[i++] = GLX_SAMPLE_BUFFERS_ARB;
   7.211 +		attr[i++] = 1;
   7.212 +		attr[i++] = GLX_SAMPLES_ARB;
   7.213 +		attr[i++] = 1;
   7.214 +	}
   7.215 +#endif	/* defined GLX_VERSION_1_4 || GLX_ARB_multisample */
   7.216 +	attr[i] = None;
   7.217 +}
   7.218 +
   7.219 +static void print_visual_info(XVisualInfo *vis)
   7.220 +{
   7.221 +	int rbits, gbits, bbits, zbits, sbits, stereo, aa, samples;
   7.222 +
   7.223 +	glXGetConfig(dpy, vis, GLX_RED_SIZE, &rbits);
   7.224 +	glXGetConfig(dpy, vis, GLX_GREEN_SIZE, &gbits);
   7.225 +	glXGetConfig(dpy, vis, GLX_BLUE_SIZE, &bbits);
   7.226 +	glXGetConfig(dpy, vis, GLX_DEPTH_SIZE, &zbits);
   7.227 +	glXGetConfig(dpy, vis, GLX_STENCIL_SIZE, &sbits);
   7.228 +	glXGetConfig(dpy, vis, GLX_STEREO, &stereo);
   7.229 +#if defined(GLX_VERSION_1_4) || defined(GLX_ARB_multisample)
   7.230 +	glXGetConfig(dpy, vis, GLX_SAMPLE_BUFFERS_ARB, &aa);
   7.231 +	if(aa) {
   7.232 +		glXGetConfig(dpy, vis, GLX_SAMPLES_ARB, &samples);
   7.233 +	} else {
   7.234 +		samples = 1;
   7.235 +	}
   7.236 +#endif	/* defined GLX_VERSION_1_4 || GLX_ARB_multisample */
   7.237 +
   7.238 +	sgl_log("got visual: %d%d%d d:%d s:%d", rbits, gbits, bbits, zbits, sbits);
   7.239 +	sgl_log(" %s", stereo ? "stereo" : "mono");
   7.240 +	sgl_log(" samples/pixel: %d\n", samples);
   7.241  }
   7.242  
   7.243  static void close_window(int id)
   7.244 @@ -87,7 +250,7 @@
   7.245  	while(win) {
   7.246  		if(win->win == id) {
   7.247  			glXDestroyContext(dpy, win->ctx);
   7.248 -			XCloseWindow(dpy, win->win);
   7.249 +			XDestroyWindow(dpy, win->win);
   7.250  			prev->next = win->next;
   7.251  			free(win);
   7.252  			return;
   7.253 @@ -95,3 +258,168 @@
   7.254  		win = win->next;
   7.255  	}
   7.256  }
   7.257 +
   7.258 +static int set_active(int id)
   7.259 +{
   7.260 +	struct window *win = winlist;
   7.261 +
   7.262 +	while(win) {
   7.263 +		if(win->win == id) {
   7.264 +			if(glXMakeCurrent(dpy, win->win, win->ctx) == False) {
   7.265 +				sgl_log("failed to activate window %d\n", id);
   7.266 +				return -1;
   7.267 +			}
   7.268 +			active_win = win;
   7.269 +			return 0;
   7.270 +		}
   7.271 +		win = win->next;
   7.272 +	}
   7.273 +
   7.274 +	sgl_log("no such window: %d\n", id);
   7.275 +	return -1;
   7.276 +}
   7.277 +
   7.278 +static int set_title(const char *str)
   7.279 +{
   7.280 +	XTextProperty wm_name;
   7.281 +
   7.282 +	if(!str || !active_win) {
   7.283 +		return -1;
   7.284 +	}
   7.285 +	XStringListToTextProperty((char**)&str, 1, &wm_name);
   7.286 +	XSetWMName(dpy, active_win->win, &wm_name);
   7.287 +	XSetWMIconName(dpy, active_win->win, &wm_name);
   7.288 +	XFree(wm_name.value);
   7.289 +	return 0;
   7.290 +}
   7.291 +
   7.292 +static void redisplay(void)
   7.293 +{
   7.294 +	active_win->redisp_pending = 1;
   7.295 +}
   7.296 +
   7.297 +static void swap_buffers(void)
   7.298 +{
   7.299 +	glXSwapBuffers(dpy, active_win->ctx);
   7.300 +}
   7.301 +
   7.302 +static void set_bits(long *mask, long bits)
   7.303 +{
   7.304 +	*mask |= bits;
   7.305 +}
   7.306 +
   7.307 +static void clear_bits(long *mask, long bits)
   7.308 +{
   7.309 +	*mask &= ~bits;
   7.310 +}
   7.311 +
   7.312 +static void set_event(int idx, int enable)
   7.313 +{
   7.314 +	void (*op)(long*, long);
   7.315 +	op = enable ? set_bits : clear_bits;
   7.316 +
   7.317 +	switch(idx) {
   7.318 +	case SGL_DISPLAY:
   7.319 +		op(&active_win->evmask, ExposureMask);
   7.320 +		break;
   7.321 +
   7.322 +	case SGL_KEYBOARD:
   7.323 +		op(&active_win->evmask, KeyPressMask | KeyReleaseMask);
   7.324 +		break;
   7.325 +
   7.326 +	case SGL_MOUSE:
   7.327 +		op(&active_win->evmask, ButtonPressMask | ButtonReleaseMask);
   7.328 +		break;
   7.329 +
   7.330 +	case SGL_MOTION:
   7.331 +		op(&active_win->evmask, ButtonMotionMask);
   7.332 +		break;
   7.333 +
   7.334 +	case SGL_PASSIVE:
   7.335 +		op(&active_win->evmask, PointerMotionMask);
   7.336 +		break;
   7.337 +
   7.338 +	default:
   7.339 +		return;
   7.340 +	}
   7.341 +
   7.342 +	XSelectInput(dpy, active_win->win, active_win->evmask);
   7.343 +}
   7.344 +
   7.345 +static int process_events(void)
   7.346 +{
   7.347 +	XEvent xev;
   7.348 +	void (*func)();
   7.349 +	int state;
   7.350 +
   7.351 +	while(XPending(dpy)) {
   7.352 +		XNextEvent(dpy, &xev);
   7.353 +
   7.354 +		switch(xev.type) {
   7.355 +		case Expose:
   7.356 +			if(xev.xexpose.count == 0) {
   7.357 +				if((func = sgl_get_callback(SGL_DISPLAY))) {
   7.358 +					func();
   7.359 +					active_win->redisp_pending = 0;
   7.360 +				}
   7.361 +			}
   7.362 +			break;
   7.363 +
   7.364 +		case MotionNotify:
   7.365 +			if(xev.xmotion.state) {
   7.366 +				func = sgl_get_callback(SGL_MOTION);
   7.367 +			} else {
   7.368 +				func = sgl_get_callback(SGL_PASSIVE);
   7.369 +			}
   7.370 +			if(func) {
   7.371 +				func(xev.xmotion.x, xev.xmotion.y);
   7.372 +			}
   7.373 +			break;
   7.374 +
   7.375 +		case ButtonPress:
   7.376 +			if(1) {
   7.377 +				state = 1;
   7.378 +			} else {
   7.379 +		case ButtonRelease:
   7.380 +				state = 0;
   7.381 +			}
   7.382 +			if((func = sgl_get_callback(SGL_MOUSE))) {
   7.383 +				int bn = xev.xbutton.button - 1;
   7.384 +				func(bn, state, xev.xbutton.x, xev.xbutton.y);
   7.385 +			}
   7.386 +			break;
   7.387 +
   7.388 +		case KeyPress:
   7.389 +			if(1) {
   7.390 +				state = 1;
   7.391 +			} else {
   7.392 +		case KeyRelease:
   7.393 +				state = 0;
   7.394 +			}
   7.395 +			if((func = sgl_get_callback(SGL_KEYBOARD))) {
   7.396 +				KeySym sym = XLookupKeysym(xev.xkey, 0);
   7.397 +				func(sym, state);
   7.398 +				/* XXX */
   7.399 +			}
   7.400 +			break;
   7.401 +
   7.402 +		case ConfigureNotify:
   7.403 +			if((func = sgl_get_callback(SGL_RESHAPE))) {
   7.404 +				func(xev.xconfigure.width, xev.xconfigure.height);
   7.405 +			}
   7.406 +			break;
   7.407 +		}
   7.408 +
   7.409 +		case ClientMessage:
   7.410 +			if(xev.xclient.message_type == xa_wm_prot) {
   7.411 +				if(xev.xclient.data.l[0] == xa_wm_del_win) {
   7.412 +					close_window(active_win->win);
   7.413 +					if(!active_win) {
   7.414 +						return 1;
   7.415 +					}
   7.416 +				}
   7.417 +			}
   7.418 +			break;
   7.419 +	}
   7.420 +	return 0;
   7.421 +}