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 +}