sgl

diff src/wsys_x11.c @ 5:0570e27e5ebc

pretty much done with the basic functionality and GLX shit
author John Tsiombikas <nuclear@siggraph.org>
date Fri, 13 May 2011 07:49:47 +0300
parents 648f8604d2b2
children 0cb438c86b98
line diff
     1.1 --- a/src/wsys_x11.c	Thu May 12 11:04:10 2011 +0300
     1.2 +++ b/src/wsys_x11.c	Fri May 13 07:49:47 2011 +0300
     1.3 @@ -5,10 +5,14 @@
     1.4  #include "wsys.h"
     1.5  #include "log.h"
     1.6  
     1.7 +
     1.8  struct window {
     1.9  	Window win;
    1.10  	GLXContext ctx;
    1.11 +	int width, height;
    1.12 +	int mapped;
    1.13  	long evmask;
    1.14 +	int redisp_pending;
    1.15  	struct window *next;
    1.16  };
    1.17  
    1.18 @@ -27,6 +31,8 @@
    1.19  
    1.20  /* window management */
    1.21  static int set_active(int id);
    1.22 +static struct window *find_window(int id);
    1.23 +static int activate_window(struct window *win);
    1.24  static int set_title(const char *str);
    1.25  static void redisplay(void);
    1.26  static void swap_buffers(void);
    1.27 @@ -36,7 +42,8 @@
    1.28  static void clear_bits(long *mask, long bits);
    1.29  static void set_event(int idx, int enable);
    1.30  static int process_events(void);
    1.31 -
    1.32 +static int handle_event(XEvent *xev);
    1.33 +static int translate_keysym(KeySym sym);
    1.34  
    1.35  static struct wsys_module ws = {
    1.36  	"x11-glx", 0,
    1.37 @@ -60,7 +67,7 @@
    1.38  static int scr;
    1.39  static Atom xa_wm_prot, xa_wm_del_win;
    1.40  static struct window *winlist;
    1.41 -static struct window *active_win;
    1.42 +static struct window *active_win, *prev_active;
    1.43  
    1.44  /* this is the only exported function, everything else should be static */
    1.45  void sgl_register_x11(void)
    1.46 @@ -70,7 +77,13 @@
    1.47  
    1.48  static int init(void)
    1.49  {
    1.50 +	if(dpy) {
    1.51 +		sgl_log("warning: double init\n");
    1.52 +		return 0;
    1.53 +	}
    1.54 +
    1.55  	winlist = 0;
    1.56 +	active_win = prev_active = 0;
    1.57  
    1.58  	if(!(dpy = XOpenDisplay(0))) {
    1.59  		sgl_log("failed to open X display: %s\n", XDisplayName(0));
    1.60 @@ -87,6 +100,10 @@
    1.61  
    1.62  static void shutdown(void)
    1.63  {
    1.64 +	if(!dpy) {
    1.65 +		return;
    1.66 +	}
    1.67 +
    1.68  	while(winlist) {
    1.69  		struct window *win = winlist;
    1.70  		winlist = winlist->next;
    1.71 @@ -171,9 +188,13 @@
    1.72  
    1.73  	wnode->win = win;
    1.74  	wnode->ctx = ctx;
    1.75 +	wnode->width = xsz;
    1.76 +	wnode->height = ysz;
    1.77 +	wnode->mapped = 0;
    1.78  	wnode->evmask = evmask;
    1.79 +	wnode->redisp_pending = 1;
    1.80  	wnode->next = winlist;
    1.81 -	winlist->next = wnode;
    1.82 +	winlist = wnode;
    1.83  
    1.84  	if(!active_win) {
    1.85  		set_active(win);
    1.86 @@ -261,22 +282,37 @@
    1.87  
    1.88  static int set_active(int id)
    1.89  {
    1.90 +	struct window *win = find_window(id);
    1.91 +	if(!win) {
    1.92 +		sgl_log("no such window: %d\n", id);
    1.93 +		return -1;
    1.94 +	}
    1.95 +	/* only the user calls this, so don't revert this selection */
    1.96 +	prev_active = win;
    1.97 +	return activate_window(win);
    1.98 +}
    1.99 +
   1.100 +static struct window *find_window(int id)
   1.101 +{
   1.102  	struct window *win = winlist;
   1.103  
   1.104  	while(win) {
   1.105  		if(win->win == id) {
   1.106 -			if(glXMakeCurrent(dpy, win->win, win->ctx) == False) {
   1.107 -				sgl_log("failed to activate window %d\n", id);
   1.108 -				return -1;
   1.109 -			}
   1.110 -			active_win = win;
   1.111 -			return 0;
   1.112 +			return win;
   1.113  		}
   1.114  		win = win->next;
   1.115  	}
   1.116 +	return 0;
   1.117 +}
   1.118  
   1.119 -	sgl_log("no such window: %d\n", id);
   1.120 -	return -1;
   1.121 +static int activate_window(struct window *win)
   1.122 +{
   1.123 +	if(glXMakeCurrent(dpy, win->win, win->ctx) == False) {
   1.124 +		sgl_log("failed to activate window %d\n", (int)win->win);
   1.125 +		return -1;
   1.126 +	}
   1.127 +	active_win = win;
   1.128 +	return 0;
   1.129  }
   1.130  
   1.131  static int set_title(const char *str)
   1.132 @@ -300,7 +336,7 @@
   1.133  
   1.134  static void swap_buffers(void)
   1.135  {
   1.136 -	glXSwapBuffers(dpy, active_win->ctx);
   1.137 +	glXSwapBuffers(dpy, active_win->win);
   1.138  }
   1.139  
   1.140  static void set_bits(long *mask, long bits)
   1.141 @@ -350,76 +386,163 @@
   1.142  {
   1.143  	XEvent xev;
   1.144  	void (*func)();
   1.145 -	int state;
   1.146 +	struct window *win;
   1.147  
   1.148 +	prev_active = active_win;
   1.149 +
   1.150 +	win = winlist;
   1.151 +	while(win) {
   1.152 +		if(win->redisp_pending && (func = sgl_get_callback(SGL_DISPLAY))) {
   1.153 +			activate_window(win);
   1.154 +			func();
   1.155 +			win->redisp_pending = 0;
   1.156 +		}
   1.157 +		win = win->next;
   1.158 +	}
   1.159 +
   1.160 +	func = sgl_get_callback(SGL_IDLE);
   1.161 +	if(!func) {
   1.162 +		XNextEvent(dpy, &xev);
   1.163 +		XPutBackEvent(dpy, &xev);
   1.164 +	}
   1.165 +
   1.166 +	/* process all pending events... */
   1.167  	while(XPending(dpy)) {
   1.168  		XNextEvent(dpy, &xev);
   1.169 +		if(handle_event(&xev) == -1) {
   1.170 +			return -1;
   1.171 +		}
   1.172  
   1.173 -		switch(xev.type) {
   1.174 -		case Expose:
   1.175 -			if(xev.xexpose.count == 0) {
   1.176 -				if((func = sgl_get_callback(SGL_DISPLAY))) {
   1.177 -					func();
   1.178 -					active_win->redisp_pending = 0;
   1.179 +		if(!dpy) {
   1.180 +			return -1;
   1.181 +		}
   1.182 +	}
   1.183 +
   1.184 +	if(func) {
   1.185 +		/* ... and then call the idle function */
   1.186 +		func();
   1.187 +	}
   1.188 +
   1.189 +	activate_window(prev_active);
   1.190 +	return 0;
   1.191 +}
   1.192 +
   1.193 +/* returns 0, or -1 when the last window gets closed */
   1.194 +static int handle_event(XEvent *xev)
   1.195 +{
   1.196 +	int state;
   1.197 +	struct window *win;
   1.198 +	void (*func)();
   1.199 +
   1.200 +	if((win = find_window(xev->xany.window))) {
   1.201 +		activate_window(win);
   1.202 +	} else {
   1.203 +		return 0;
   1.204 +	}
   1.205 +
   1.206 +	switch(xev->type) {
   1.207 +	case MapNotify:
   1.208 +		active_win->mapped = 1;
   1.209 +		break;
   1.210 +
   1.211 +	case UnmapNotify:
   1.212 +		active_win->mapped = 0;
   1.213 +		break;
   1.214 +
   1.215 +	case Expose:
   1.216 +		if(active_win->mapped && xev->xexpose.count == 0) {
   1.217 +			if((func = sgl_get_callback(SGL_DISPLAY))) {
   1.218 +				func();
   1.219 +				active_win->redisp_pending = 0;
   1.220 +			}
   1.221 +		}
   1.222 +		break;
   1.223 +
   1.224 +	case MotionNotify:
   1.225 +		if(xev->xmotion.state) {
   1.226 +			func = sgl_get_callback(SGL_MOTION);
   1.227 +		} else {
   1.228 +			func = sgl_get_callback(SGL_PASSIVE);
   1.229 +		}
   1.230 +		if(func) {
   1.231 +			func(xev->xmotion.x, xev->xmotion.y);
   1.232 +		}
   1.233 +		break;
   1.234 +
   1.235 +	case ButtonPress:
   1.236 +		if(1) {
   1.237 +			state = 1;
   1.238 +		} else {
   1.239 +	case ButtonRelease:
   1.240 +			state = 0;
   1.241 +		}
   1.242 +		if((func = sgl_get_callback(SGL_MOUSE))) {
   1.243 +			int bn = xev->xbutton.button - 1;
   1.244 +			func(bn, state, xev->xbutton.x, xev->xbutton.y);
   1.245 +		}
   1.246 +		break;
   1.247 +
   1.248 +	case KeyPress:
   1.249 +		if(1) {
   1.250 +			state = 1;
   1.251 +		} else {
   1.252 +	case KeyRelease:
   1.253 +			state = 0;
   1.254 +		}
   1.255 +		if((func = sgl_get_callback(SGL_KEYBOARD))) {
   1.256 +			KeySym sym = XLookupKeysym(&xev->xkey, 0);
   1.257 +			func(translate_keysym(sym), state);
   1.258 +		}
   1.259 +		break;
   1.260 +
   1.261 +	case ConfigureNotify:
   1.262 +		if((func = sgl_get_callback(SGL_RESHAPE))) {
   1.263 +			if(xev->xconfigure.width != active_win->width || xev->xconfigure.height != active_win->height) {
   1.264 +				active_win->width = xev->xconfigure.width;
   1.265 +				active_win->height = xev->xconfigure.height;
   1.266 +
   1.267 +				func(xev->xconfigure.width, xev->xconfigure.height);
   1.268 +			}
   1.269 +		}
   1.270 +		break;
   1.271 +
   1.272 +	case ClientMessage:
   1.273 +		if(xev->xclient.message_type == xa_wm_prot) {
   1.274 +			if(xev->xclient.data.l[0] == xa_wm_del_win) {
   1.275 +				close_window(active_win->win);
   1.276 +				if(!active_win) {
   1.277 +					return -1;
   1.278  				}
   1.279  			}
   1.280 -			break;
   1.281 +		}
   1.282 +		break;
   1.283  
   1.284 -		case MotionNotify:
   1.285 -			if(xev.xmotion.state) {
   1.286 -				func = sgl_get_callback(SGL_MOTION);
   1.287 -			} else {
   1.288 -				func = sgl_get_callback(SGL_PASSIVE);
   1.289 -			}
   1.290 -			if(func) {
   1.291 -				func(xev.xmotion.x, xev.xmotion.y);
   1.292 -			}
   1.293 -			break;
   1.294 +	default:
   1.295 +		break;
   1.296 +	}
   1.297  
   1.298 -		case ButtonPress:
   1.299 -			if(1) {
   1.300 -				state = 1;
   1.301 -			} else {
   1.302 -		case ButtonRelease:
   1.303 -				state = 0;
   1.304 -			}
   1.305 -			if((func = sgl_get_callback(SGL_MOUSE))) {
   1.306 -				int bn = xev.xbutton.button - 1;
   1.307 -				func(bn, state, xev.xbutton.x, xev.xbutton.y);
   1.308 -			}
   1.309 -			break;
   1.310 -
   1.311 -		case KeyPress:
   1.312 -			if(1) {
   1.313 -				state = 1;
   1.314 -			} else {
   1.315 -		case KeyRelease:
   1.316 -				state = 0;
   1.317 -			}
   1.318 -			if((func = sgl_get_callback(SGL_KEYBOARD))) {
   1.319 -				KeySym sym = XLookupKeysym(xev.xkey, 0);
   1.320 -				func(sym, state);
   1.321 -				/* XXX */
   1.322 -			}
   1.323 -			break;
   1.324 -
   1.325 -		case ConfigureNotify:
   1.326 -			if((func = sgl_get_callback(SGL_RESHAPE))) {
   1.327 -				func(xev.xconfigure.width, xev.xconfigure.height);
   1.328 -			}
   1.329 -			break;
   1.330 -		}
   1.331 -
   1.332 -		case ClientMessage:
   1.333 -			if(xev.xclient.message_type == xa_wm_prot) {
   1.334 -				if(xev.xclient.data.l[0] == xa_wm_del_win) {
   1.335 -					close_window(active_win->win);
   1.336 -					if(!active_win) {
   1.337 -						return 1;
   1.338 -					}
   1.339 -				}
   1.340 -			}
   1.341 -			break;
   1.342 -	}
   1.343  	return 0;
   1.344  }
   1.345 +
   1.346 +static int translate_keysym(KeySym sym)
   1.347 +{
   1.348 +	if(sym < 256) {
   1.349 +		return sym;
   1.350 +	}
   1.351 +
   1.352 +	switch(sym) {
   1.353 +	case XK_BackSpace:
   1.354 +		return '\b';
   1.355 +	case XK_Tab:
   1.356 +		return '\t';
   1.357 +	case XK_Linefeed:
   1.358 +		return '\r';
   1.359 +	case XK_Return:
   1.360 +		return '\n';
   1.361 +	case XK_Escape:
   1.362 +		return 27;
   1.363 +	default:
   1.364 +		break;
   1.365 +	}
   1.366 +	return (int)sym;
   1.367 +}