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 *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 void
49 usage(void)
50 {
51 fprint(2, "usage: xshove [window rectangle]\n");
52 exits("usage");
53 }
55 void
56 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 }ARGEND
70 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);
105 Window
106 findname(Window w)
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;
122 void
123 getinfo(void)
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);
159 ww->iconname = getproperty(ww->xw, XA_WM_ICON_NAME);
160 ww->name = getproperty(ww->xw, XA_WM_NAME);
161 ww++;
163 nw = ww - w;
166 void
167 listwindows(void)
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);
183 void
184 shove(char *name, char *geom)
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;
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;
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;
223 value_mask = CWX | CWY | CWWidth | CWHeight;
224 XConfigureWindow(dpy, ww->xw, value_mask, &e);
225 XFlush(dpy);
230 int
231 parsewinsize(char *s, Rectangle *r, int *isdelta, int *havemin, int *havesize)
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 }else
244 *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;
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;
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;