xgetshape
changeset 1:9b560415bad4
blured shadow
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 03 Nov 2015 04:08:32 +0200 |
parents | 2f02f100b20f |
children | b832d3b3ed98 |
files | src/main.c src/texture.c src/texture.h |
diffstat | 3 files changed, 165 insertions(+), 63 deletions(-) [+] |
line diff
1.1 --- a/src/main.c Tue Nov 03 00:42:08 2015 +0200 1.2 +++ b/src/main.c Tue Nov 03 04:08:32 2015 +0200 1.3 @@ -1,6 +1,7 @@ 1.4 #include <stdio.h> 1.5 #include <stdlib.h> 1.6 #include <X11/Xlib.h> 1.7 +#include <X11/cursorfont.h> 1.8 #include <X11/extensions/shape.h> 1.9 #include <GL/glx.h> 1.10 #include "image.h" 1.11 @@ -14,6 +15,7 @@ 1.12 Window create_window(int xsz, int ysz); 1.13 void set_window_title(Window win, const char *title); 1.14 int get_window_shape(Window win, struct image *img); 1.15 +XID get_window_id(Display *dpy, int screen, int button); 1.16 1.17 Display *dpy; 1.18 Window win; 1.19 @@ -26,6 +28,8 @@ 1.20 struct texture tex; 1.21 struct texture chess_tex; 1.22 float aspect; 1.23 +int sel_active; 1.24 +Cursor sel_cursor; 1.25 1.26 unsigned int target_xid = 0; 1.27 1.28 @@ -35,11 +39,7 @@ 1.29 char *endp; 1.30 struct image chess_img; 1.31 1.32 - if(!argv[1]) { 1.33 - fprintf(stderr, "pass the window id to use\n"); 1.34 - return 1; 1.35 - } 1.36 - if(!(target_xid = strtol(argv[1], &endp, 0))) { 1.37 + if(argv[1] && !(target_xid = strtol(argv[1], &endp, 0))) { 1.38 fprintf(stderr, "invalid argument: %s\n", argv[1]); 1.39 return 1; 1.40 } 1.41 @@ -51,36 +51,53 @@ 1.42 xa_wm_prot = XInternAtom(dpy, "WM_PROTOCOLS", False); 1.43 xa_wm_del_win = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 1.44 1.45 + sel_cursor = XCreateFontCursor(dpy, XC_crosshair); 1.46 + 1.47 if(!XShapeQueryExtension(dpy, &event_base, &error_base)) { 1.48 fprintf(stderr, "shape extension unsupported by this X server\n"); 1.49 XCloseDisplay(dpy); 1.50 return 1; 1.51 } 1.52 - if(get_window_shape(target_xid, &img) == -1) { 1.53 - XCloseDisplay(dpy); 1.54 + 1.55 + if(!target_xid) { 1.56 + target_xid = get_window_id(dpy, 0, Button1); 1.57 + } 1.58 + if(target_xid) { 1.59 + image_destroy(&img); 1.60 + if(get_window_shape(target_xid, &img) == -1) { 1.61 + destroy_texture(&tex); 1.62 + } 1.63 + } 1.64 + 1.65 + if(!(win = create_window(800 * (float)img.width / (float)img.height, 800))) { 1.66 return 1; 1.67 } 1.68 - 1.69 - if(!(win = create_window(1280, 800))) { 1.70 - return 1; 1.71 + if(img.pixels) { 1.72 + image_texture(&tex, &img); 1.73 } 1.74 1.75 - image_texture(&tex, &img); 1.76 - 1.77 image_create(&chess_img, 256, 256); 1.78 - image_chess(&chess_img, 8, 255, 128, 64, 64, 128, 255); 1.79 + image_chess(&chess_img, 8, 192, 100, 64, 64, 100, 192); 1.80 image_texture(&chess_tex, &chess_img); 1.81 image_destroy(&chess_img); 1.82 1.83 for(;;) { 1.84 XEvent ev; 1.85 - XNextEvent(dpy, &ev); 1.86 1.87 - if(handle_event(&ev) == -1) { 1.88 - break; 1.89 + do { 1.90 + XNextEvent(dpy, &ev); 1.91 + if(handle_event(&ev) == -1) { 1.92 + goto quit; 1.93 + } 1.94 + } while(XPending(dpy)); 1.95 + 1.96 + if(redisp_pending) { 1.97 + redisp_pending = 0; 1.98 + redraw(); 1.99 } 1.100 } 1.101 1.102 +quit: 1.103 XDestroyWindow(dpy, win); 1.104 XCloseDisplay(dpy); 1.105 return 0; 1.106 @@ -100,54 +117,67 @@ 1.107 1.108 /* background */ 1.109 glBegin(GL_QUADS); 1.110 + glColor3f(1, 1, 1); 1.111 glTexCoord2f(0, 0); glVertex2f(-aspect, -1); 1.112 - glTexCoord2f(1, 0); glVertex2f(aspect, -1); 1.113 - glTexCoord2f(1, 1); glVertex2f(aspect, 1); 1.114 + glTexCoord2f(aspect, 0); glVertex2f(aspect, -1); 1.115 + glTexCoord2f(aspect, 1); glVertex2f(aspect, 1); 1.116 glTexCoord2f(0, 1); glVertex2f(-aspect, 1); 1.117 glEnd(); 1.118 1.119 - /* draw the window shape */ 1.120 - glEnable(GL_BLEND); 1.121 - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1.122 + if(tex.id) { 1.123 + int i, ssamples = 64; 1.124 + float ssample_weight = 1.0 / (float)ssamples; 1.125 + float shadow_spread = 0.05; 1.126 + float img_aspect = (float)tex.width / (float)tex.height; 1.127 1.128 - glBindTexture(GL_TEXTURE_2D, tex.id); 1.129 - glMatrixMode(GL_TEXTURE); 1.130 - glLoadIdentity(); 1.131 - glScalef((float)tex.width / (float)tex.tex_width, 1.132 - (float)tex.height / (float)tex.tex_height, 1.133 - 1.0); 1.134 + /* draw the window shape */ 1.135 + glEnable(GL_BLEND); 1.136 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 1.137 1.138 - glMatrixMode(GL_MODELVIEW); 1.139 - glPushMatrix(); 1.140 - glScalef(0.7, 0.7, 0.7); 1.141 + glBindTexture(GL_TEXTURE_2D, tex.id); 1.142 + glMatrixMode(GL_TEXTURE); 1.143 + glLoadIdentity(); 1.144 + glScalef((float)tex.width / (float)tex.tex_width, 1.145 + (float)tex.height / (float)tex.tex_height, 1.146 + 1.0); 1.147 1.148 - /* shadow */ 1.149 - glPushMatrix(); 1.150 - glTranslatef(0.1, -0.1, 0); 1.151 - glBegin(GL_QUADS); 1.152 - glColor3f(0, 0, 0); 1.153 - glTexCoord2f(0, 1); glVertex2f(-1, -1); 1.154 - glTexCoord2f(1, 1); glVertex2f(1, -1); 1.155 - glTexCoord2f(1, 0); glVertex2f(1, 1); 1.156 - glTexCoord2f(0, 0); glVertex2f(-1, 1); 1.157 - glEnd(); 1.158 - glPopMatrix(); 1.159 + glMatrixMode(GL_MODELVIEW); 1.160 + glPushMatrix(); 1.161 + glScalef(0.9 * img_aspect, 0.9, 0.9); 1.162 1.163 - /* window */ 1.164 - glBegin(GL_QUADS); 1.165 - glColor3f(1, 1, 0); 1.166 - glTexCoord2f(0, 1); glVertex2f(-1, -1); 1.167 - glTexCoord2f(1, 1); glVertex2f(1, -1); 1.168 - glTexCoord2f(1, 0); glVertex2f(1, 1); 1.169 - glTexCoord2f(0, 0); glVertex2f(-1, 1); 1.170 - glEnd(); 1.171 + /* shadow */ 1.172 + for(i=0; i<ssamples; i++) { 1.173 + float xoffs = shadow_spread * ((float)rand() / (float)RAND_MAX - 0.5f); 1.174 + float yoffs = shadow_spread * ((float)rand() / (float)RAND_MAX - 0.5f); 1.175 1.176 - glMatrixMode(GL_TEXTURE); 1.177 - glLoadIdentity(); 1.178 - glMatrixMode(GL_MODELVIEW); 1.179 - glPopMatrix(); 1.180 + glPushMatrix(); 1.181 + glTranslatef(0.075 + xoffs, -0.075 + yoffs, 0); 1.182 + glBegin(GL_QUADS); 1.183 + glColor4f(0, 0, 0, ssample_weight); 1.184 + glTexCoord2f(0, 1); glVertex2f(-1, -1); 1.185 + glTexCoord2f(1, 1); glVertex2f(1, -1); 1.186 + glTexCoord2f(1, 0); glVertex2f(1, 1); 1.187 + glTexCoord2f(0, 0); glVertex2f(-1, 1); 1.188 + glEnd(); 1.189 + glPopMatrix(); 1.190 + } 1.191 1.192 - glDisable(GL_BLEND); 1.193 + /* window */ 1.194 + glBegin(GL_QUADS); 1.195 + glColor3f(1, 1, 0); 1.196 + glTexCoord2f(0, 1); glVertex2f(-1, -1); 1.197 + glTexCoord2f(1, 1); glVertex2f(1, -1); 1.198 + glTexCoord2f(1, 0); glVertex2f(1, 1); 1.199 + glTexCoord2f(0, 0); glVertex2f(-1, 1); 1.200 + glEnd(); 1.201 + 1.202 + glMatrixMode(GL_TEXTURE); 1.203 + glLoadIdentity(); 1.204 + glMatrixMode(GL_MODELVIEW); 1.205 + glPopMatrix(); 1.206 + 1.207 + glDisable(GL_BLEND); 1.208 + } 1.209 1.210 glXSwapBuffers(dpy, win); 1.211 } 1.212 @@ -171,9 +201,7 @@ 1.213 break; 1.214 1.215 case Expose: 1.216 - if(mapped && ev->xexpose.count == 0) { 1.217 - redraw(); 1.218 - } 1.219 + redisp_pending = 1; 1.220 break; 1.221 1.222 case KeyPress: 1.223 @@ -183,6 +211,17 @@ 1.224 switch(sym) { 1.225 case XK_Escape: 1.226 return -1; 1.227 + 1.228 + case ' ': 1.229 + target_xid = get_window_id(dpy, 0, Button1); 1.230 + image_destroy(&img); 1.231 + if(get_window_shape(target_xid, &img) == -1) { 1.232 + destroy_texture(&tex); 1.233 + } else { 1.234 + image_texture(&tex, &img); 1.235 + redisp_pending = 1; 1.236 + } 1.237 + break; 1.238 } 1.239 } 1.240 break; 1.241 @@ -202,6 +241,20 @@ 1.242 } 1.243 } 1.244 break; 1.245 + 1.246 + case ButtonPress: 1.247 + /*if(sel_active && ev->xbutton.button == Button1) { 1.248 + target_xid = ev->xbutton.subwindow; 1.249 + printf("clicked on window: %x\n", target_xid); 1.250 + 1.251 + image_destroy(&img); 1.252 + if(get_window_shape(target_xid, &img) == -1) { 1.253 + destroy_texture(&tex); 1.254 + } else { 1.255 + image_texture(&tex, &img); 1.256 + } 1.257 + }*/ 1.258 + break; 1.259 } 1.260 return 0; 1.261 } 1.262 @@ -280,21 +333,17 @@ 1.263 int bx, by, cx, cy; 1.264 unsigned int bw, bh, cw, ch; 1.265 int kind; 1.266 - int x, y, w, h; 1.267 + int w, h; 1.268 XRectangle *rects; 1.269 int i, rect_count, rect_order; 1.270 1.271 XShapeQueryExtents(dpy, win, &buse, &bx, &by, &bw, &bh, 1.272 - &cuse, &cx, &cy, &bw, &bh); 1.273 + &cuse, &cx, &cy, &cw, &ch); 1.274 if(cuse) { 1.275 - x = cx; 1.276 - y = cy; 1.277 w = cw; 1.278 h = ch; 1.279 kind = ShapeClip; 1.280 } else if(buse) { 1.281 - x = bx; 1.282 - y = by; 1.283 w = bw; 1.284 h = bh; 1.285 kind = ShapeBounding; 1.286 @@ -321,3 +370,49 @@ 1.287 } 1.288 return 0; 1.289 } 1.290 + 1.291 +XID get_window_id(Display *dpy, int screen, int button) 1.292 +{ 1.293 + Window root; /* the current root */ 1.294 + Window retwin = None; /* the window that got selected */ 1.295 + int retbutton = -1; /* button used to select window */ 1.296 + int pressed = 0; /* count of number of buttons pressed */ 1.297 + 1.298 +#define MASK (ButtonPressMask | ButtonReleaseMask) 1.299 + 1.300 + root = RootWindow(dpy, screen); 1.301 + XSync(dpy, 0); /* give xterm a chance */ 1.302 + 1.303 + if(XGrabPointer(dpy, root, False, MASK, GrabModeSync, GrabModeAsync, 1.304 + None, sel_cursor, CurrentTime) != GrabSuccess) { 1.305 + fprintf (stderr, "unable to grab cursor\n"); 1.306 + return 0; 1.307 + } 1.308 + 1.309 + while (retwin == None || pressed != 0) { 1.310 + XEvent event; 1.311 + 1.312 + XAllowEvents (dpy, SyncPointer, CurrentTime); 1.313 + XWindowEvent (dpy, root, MASK, &event); 1.314 + 1.315 + switch (event.type) { 1.316 + case ButtonPress: 1.317 + if (retwin == None) { 1.318 + retbutton = event.xbutton.button; 1.319 + retwin = ((event.xbutton.subwindow != None) ? 1.320 + event.xbutton.subwindow : root); 1.321 + } 1.322 + pressed++; 1.323 + continue; 1.324 + 1.325 + case ButtonRelease: 1.326 + if (pressed > 0) pressed--; 1.327 + continue; 1.328 + } /* end switch */ 1.329 + } /* end for */ 1.330 + 1.331 + XUngrabPointer (dpy, CurrentTime); 1.332 + XSync (dpy, 0); 1.333 + 1.334 + return ((button == -1 || retbutton == button) ? retwin : None); 1.335 +}
2.1 --- a/src/texture.c Tue Nov 03 00:42:08 2015 +0200 2.2 +++ b/src/texture.c Tue Nov 03 04:08:32 2015 +0200 2.3 @@ -22,6 +22,12 @@ 2.4 return 0; 2.5 } 2.6 2.7 +void destroy_texture(struct texture *tex) 2.8 +{ 2.9 + glDeleteTextures(1, &tex->id); 2.10 + tex->id = 0; 2.11 +} 2.12 + 2.13 static int next_pow2(int x) 2.14 { 2.15 --x;