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 Rectangle
13 {
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 Win
24 {
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 void
48 usage(void)
49 {
50 fprint(2, "usage: xshove [window rectangle]\n");
51 exits("usage");
52 }
54 void
55 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 }ARGEND
69 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);
104 Window
105 findname(Window w)
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;
121 void
122 getinfo(void)
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);
155 ww->iconname = getproperty(ww->xw, XA_WM_ICON_NAME);
156 ww->name = getproperty(ww->xw, XA_WM_NAME);
157 ww++;
159 nw = ww - w;
162 void
163 listwindows(void)
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);
179 void
180 shove(char *name, char *geom)
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;
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;
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;
218 value_mask = CWX | CWY | CWWidth | CWHeight;
219 XConfigureWindow(dpy, ww->xw, value_mask, &e);
220 XFlush(dpy);
225 int
226 parsewinsize(char *s, Rectangle *r, int *isdelta, int *havemin, int *havesize)
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 }else
239 *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;
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;
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;