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 *idstr;31 char *class;32 char *instance;33 char *name;34 char *iconname;35 };37 Display *dpy;38 Window root;40 Win *w;41 int nw;43 void getinfo(void);44 void listwindows(void);45 int parsewinsize(char*, Rectangle*, int*, int*, int*);46 void shove(char*, char*);48 void49 usage(void)50 {51 fprint(2, "usage: xshove [window rectangle]\n");52 exits("usage");53 }55 void56 main(int argc, char **argv)57 {58 int screen;60 screen = 0;61 ARGBEGIN{62 case 's':63 screen = atoi(EARGF(usage()));64 break;65 default:66 usage();67 break;68 }ARGEND70 dpy = XOpenDisplay("");71 if(dpy == nil)72 sysfatal("open display: %r");74 root = RootWindow(dpy, screen);75 getinfo();77 if(argc == 0){78 listwindows();79 exits(0);80 }81 if(argc != 2)82 usage();83 shove(argv[0], argv[1]);84 exits(0);85 }87 char*88 getproperty(Window w, Atom a)89 {90 uchar *p;91 int fmt;92 Atom type;93 ulong n, dummy;95 n = 100;96 p = nil;97 XGetWindowProperty(dpy, w, a, 0, 100L, 0,98 AnyPropertyType, &type, &fmt,99 &n, &dummy, &p);100 if(p == nil || *p == 0)101 return nil;102 return strdup((char*)p);103 }105 Window106 findname(Window w)107 {108 int i;109 uint nxwin;110 Window dw1, dw2, *xwin;112 if(getproperty(w, XA_WM_NAME))113 return w;114 if(!XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin))115 return 0;116 for(i=0; i<nxwin; i++)117 if((w = findname(xwin[i])) != 0)118 return w;119 return 0;120 }122 void123 getinfo(void)124 {125 int i;126 uint nxwin;127 Window dw1, dw2, *xwin;128 XClassHint class;129 XWindowAttributes attr;131 if(!XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin))132 return;133 w = mallocz(nxwin*sizeof w[0], 1);134 if(w == 0)135 sysfatal("malloc: %r");137 Win *ww = w;138 for(i=0; i<nxwin; i++){139 memset(&attr, 0, sizeof attr);140 xwin[i] = findname(xwin[i]);141 if(xwin[i] == 0)142 continue;143 XGetWindowAttributes(dpy, xwin[i], &attr);144 if(attr.width <= 0 || attr.override_redirect || attr.map_state != IsViewable)145 continue;146 ww->xw = xwin[i];147 char idstr[9];148 snprint(idstr, sizeof(idstr), "%08x", (uint)ww->xw);149 ww->idstr = strdup(idstr);150 ww->x = attr.x;151 ww->y = attr.y;152 ww->dx = attr.width;153 ww->dy = attr.height;154 XTranslateCoordinates(dpy, ww->xw, root, 0, 0, &ww->x, &ww->y, &dw1);155 if(XGetClassHint(dpy, ww->xw, &class)){156 ww->class = strdup(class.res_class);157 ww->instance = strdup(class.res_name);158 }159 ww->iconname = getproperty(ww->xw, XA_WM_ICON_NAME);160 ww->name = getproperty(ww->xw, XA_WM_NAME);161 ww++;162 }163 nw = ww - w;164 }166 void167 listwindows(void)168 {169 int i;171 for(i=0; i<nw; i++){172 Win *ww = &w[i];173 char rect[50];174 snprint(rect, sizeof rect, "%d,%d,%d,%d", ww->x, ww->y, ww->x+ww->dx, ww->y+ww->dy);175 print("%08x %-20s %-10s %s\n",176 (uint)ww->xw,177 rect,178 ww->instance,179 ww->class);180 }181 }183 void184 shove(char *name, char *geom)185 {186 int i;187 int isdelta, havemin, havesize;188 int old, new;189 Rectangle r;191 if(parsewinsize(geom, &r, &isdelta, &havemin, &havesize) < 0)192 sysfatal("bad window spec: %s", name);194 old = 0;195 new = 1;196 if(isdelta){197 old = 1;198 new = isdelta;199 }200 for(i=0; i<nw; i++){201 Win *ww = &w[i];202 if(ww->instance && strstr(ww->instance, name)203 || ww->class && strstr(ww->class, name)204 || ww->idstr && strstr(ww->idstr, name)){205 int value_mask;206 XWindowChanges e;208 memset(&e, 0, sizeof e);209 if(havemin){210 e.x = old*ww->x + new*r.min.x;211 e.y = old*ww->y + new*r.min.y;212 }else{213 e.x = ww->x;214 e.y = ww->y;215 }216 if(havesize){217 e.width = old*ww->dx + new*Dx(r);218 e.height = old*ww->dy + new*Dy(r);219 }else{220 e.width = ww->dx;221 e.height = ww->dy;222 }223 value_mask = CWX | CWY | CWWidth | CWHeight;224 XConfigureWindow(dpy, ww->xw, value_mask, &e);225 XFlush(dpy);226 }227 }228 }230 int231 parsewinsize(char *s, Rectangle *r, int *isdelta, int *havemin, int *havesize)232 {233 char c, *os;234 int i, j, k, l;236 os = s;237 if(*s == '-'){238 s++;239 *isdelta = -1;240 }else if(*s == '+'){241 s++;242 *isdelta = 1;243 }else244 *isdelta = 0;245 *havemin = 0;246 *havesize = 0;247 memset(r, 0, sizeof *r);248 if(!isdigit((uchar)*s))249 goto oops;250 i = strtol(s, &s, 0);251 if(*s == 'x'){252 s++;253 if(!isdigit((uchar)*s))254 goto oops;255 j = strtol(s, &s, 0);256 r->max.x = i;257 r->max.y = j;258 *havesize = 1;259 if(*s == 0)260 return 0;261 if(*s != '@')262 goto oops;264 s++;265 if(!isdigit((uchar)*s))266 goto oops;267 i = strtol(s, &s, 0);268 if(*s != ',' && *s != ' ')269 goto oops;270 s++;271 if(!isdigit((uchar)*s))272 goto oops;273 j = strtol(s, &s, 0);274 if(*s != 0)275 goto oops;276 r->min.x += i;277 r->max.x += i;278 r->min.y += j;279 r->max.y += j;280 *havesize = 1;281 *havemin = 1;282 return 0;283 }285 c = *s;286 if(c != ' ' && c != ',')287 goto oops;288 s++;289 if(!isdigit((uchar)*s))290 goto oops;291 j = strtol(s, &s, 0);292 if(*s == 0){293 r->min.x = i;294 r->min.y = j;295 *havemin = 1;296 return 0;297 }298 if(*s != c)299 goto oops;300 s++;301 if(!isdigit((uchar)*s))302 goto oops;303 k = strtol(s, &s, 0);304 if(*s != c)305 goto oops;306 s++;307 if(!isdigit((uchar)*s))308 goto oops;309 l = strtol(s, &s, 0);310 if(*s != 0)311 goto oops;312 r->min.x = i;313 r->min.y = j;314 r->max.x = k;315 r->max.y = l;316 *havemin = 1;317 *havesize = 1;318 return 0;320 oops:321 werrstr("bad syntax in window size '%s'", os);322 return -1;323 }