Blob
1 #include <u.h>2 #include <X11/X.h>3 #include <X11/Xatom.h>4 #include <X11/Xlib.h>5 #include <X11/Xutil.h>6 #include <libc.h>7 #include <ctype.h>9 AUTOLIB(X11);11 typedef struct Rectangle Rectangle;12 struct Rectangle13 {14 struct {15 int x;16 int y;17 } min, max;18 };19 #define Dx(r) ((r).max.x - (r).min.x)20 #define Dy(r) ((r).max.y - (r).min.y)22 typedef struct Win Win;23 struct Win24 {25 Window xw;26 int x;27 int y;28 int dx;29 int dy;30 char *class;31 char *instance;32 char *name;33 char *iconname;34 };36 Display *dpy;37 Window root;39 Win *w;40 int nw;42 void getinfo(void);43 void listwindows(void);44 int parsewinsize(char*, Rectangle*, int*, int*, int*);45 void shove(char*, char*);47 void48 usage(void)49 {50 fprint(2, "usage: xshove [window rectangle]\n");51 exits("usage");52 }54 void55 main(int argc, char **argv)56 {57 int screen;59 screen = 0;60 ARGBEGIN{61 case 's':62 screen = atoi(EARGF(usage()));63 break;64 default:65 usage();66 break;67 }ARGEND69 dpy = XOpenDisplay("");70 if(dpy == nil)71 sysfatal("open display: %r");73 root = RootWindow(dpy, screen);74 getinfo();76 if(argc == 0){77 listwindows();78 exits(0);79 }80 if(argc != 2)81 usage();82 shove(argv[0], argv[1]);83 exits(0);84 }86 char*87 getproperty(Window w, Atom a)88 {89 uchar *p;90 int fmt;91 Atom type;92 ulong n, dummy;94 n = 100;95 p = nil;96 XGetWindowProperty(dpy, w, a, 0, 100L, 0,97 AnyPropertyType, &type, &fmt,98 &n, &dummy, &p);99 if(p == nil || *p == 0)100 return nil;101 return strdup((char*)p);102 }104 Window105 findname(Window w)106 {107 int i;108 uint nxwin;109 Window dw1, dw2, *xwin;111 if(getproperty(w, XA_WM_NAME))112 return w;113 if(!XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin))114 return 0;115 for(i=0; i<nxwin; i++)116 if((w = findname(xwin[i])) != 0)117 return w;118 return 0;119 }121 void122 getinfo(void)123 {124 int i;125 uint nxwin;126 Window dw1, dw2, *xwin;127 XClassHint class;128 XWindowAttributes attr;130 if(!XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin))131 return;132 w = mallocz(nxwin*sizeof w[0], 1);133 if(w == 0)134 sysfatal("malloc: %r");136 Win *ww = w;137 for(i=0; i<nxwin; i++){138 memset(&attr, 0, sizeof attr);139 xwin[i] = findname(xwin[i]);140 if(xwin[i] == 0)141 continue;142 XGetWindowAttributes(dpy, xwin[i], &attr);143 if(attr.width <= 0 || attr.override_redirect || attr.map_state != IsViewable)144 continue;145 ww->xw = xwin[i];146 ww->x = attr.x;147 ww->y = attr.y;148 ww->dx = attr.width;149 ww->dy = attr.height;150 XTranslateCoordinates(dpy, ww->xw, root, 0, 0, &ww->x, &ww->y, &dw1);151 if(XGetClassHint(dpy, ww->xw, &class)){152 ww->class = strdup(class.res_class);153 ww->instance = strdup(class.res_name);154 }155 ww->iconname = getproperty(ww->xw, XA_WM_ICON_NAME);156 ww->name = getproperty(ww->xw, XA_WM_NAME);157 ww++;158 }159 nw = ww - w;160 }162 void163 listwindows(void)164 {165 int i;167 for(i=0; i<nw; i++){168 Win *ww = &w[i];169 char rect[50];170 snprint(rect, sizeof rect, "%d,%d,%d,%d", ww->x, ww->y, ww->x+ww->dx, ww->y+ww->dy);171 print("%08x %-20s %-10s %s\n",172 (uint)ww->xw,173 rect,174 ww->instance,175 ww->class);176 }177 }179 void180 shove(char *name, char *geom)181 {182 int i;183 int isdelta, havemin, havesize;184 int old, new;185 Rectangle r;187 if(parsewinsize(geom, &r, &isdelta, &havemin, &havesize) < 0)188 sysfatal("bad window spec: %s", name);190 old = 0;191 new = 1;192 if(isdelta){193 old = 1;194 new = isdelta;195 }196 for(i=0; i<nw; i++){197 Win *ww = &w[i];198 if(ww->instance && strstr(ww->instance, name)199 || ww->class && strstr(ww->class, name)){200 int value_mask;201 XWindowChanges e;203 memset(&e, 0, sizeof e);204 if(havemin){205 e.x = old*ww->x + new*r.min.x;206 e.y = old*ww->y + new*r.min.y;207 }else{208 e.x = ww->x;209 e.y = ww->y;210 }211 if(havesize){212 e.width = old*ww->dx + new*Dx(r);213 e.height = old*ww->dy + new*Dy(r);214 }else{215 e.width = ww->dx;216 e.height = ww->dy;217 }218 value_mask = CWX | CWY | CWWidth | CWHeight;219 XConfigureWindow(dpy, ww->xw, value_mask, &e);220 XFlush(dpy);221 }222 }223 }225 int226 parsewinsize(char *s, Rectangle *r, int *isdelta, int *havemin, int *havesize)227 {228 char c, *os;229 int i, j, k, l;231 os = s;232 if(*s == '-'){233 s++;234 *isdelta = -1;235 }else if(*s == '+'){236 s++;237 *isdelta = 1;238 }else239 *isdelta = 0;240 *havemin = 0;241 *havesize = 0;242 memset(r, 0, sizeof *r);243 if(!isdigit((uchar)*s))244 goto oops;245 i = strtol(s, &s, 0);246 if(*s == 'x'){247 s++;248 if(!isdigit((uchar)*s))249 goto oops;250 j = strtol(s, &s, 0);251 r->max.x = i;252 r->max.y = j;253 *havesize = 1;254 if(*s == 0)255 return 0;256 if(*s != '@')257 goto oops;259 s++;260 if(!isdigit((uchar)*s))261 goto oops;262 i = strtol(s, &s, 0);263 if(*s != ',' && *s != ' ')264 goto oops;265 s++;266 if(!isdigit((uchar)*s))267 goto oops;268 j = strtol(s, &s, 0);269 if(*s != 0)270 goto oops;271 r->min.x += i;272 r->max.x += i;273 r->min.y += j;274 r->max.y += j;275 *havesize = 1;276 *havemin = 1;277 return 0;278 }280 c = *s;281 if(c != ' ' && c != ',')282 goto oops;283 s++;284 if(!isdigit((uchar)*s))285 goto oops;286 j = strtol(s, &s, 0);287 if(*s == 0){288 r->min.x = i;289 r->min.y = j;290 *havemin = 1;291 return 0;292 }293 if(*s != c)294 goto oops;295 s++;296 if(!isdigit((uchar)*s))297 goto oops;298 k = strtol(s, &s, 0);299 if(*s != c)300 goto oops;301 s++;302 if(!isdigit((uchar)*s))303 goto oops;304 l = strtol(s, &s, 0);305 if(*s != 0)306 goto oops;307 r->min.x = i;308 r->min.y = j;309 r->max.x = k;310 r->max.y = l;311 *havemin = 1;312 *havesize = 1;313 return 0;315 oops:316 werrstr("bad syntax in window size '%s'", os);317 return -1;318 }