plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

xshove.c (5419B)


      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>
      8 
      9 AUTOLIB(X11);
     10 
     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)
     21 
     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 };
     36 
     37 Display *dpy;
     38 Window root;
     39 
     40 Win *w;
     41 int nw;
     42 
     43 void getinfo(void);
     44 void listwindows(void);
     45 int parsewinsize(char*, Rectangle*, int*, int*, int*);
     46 void shove(char*, char*);
     47 
     48 void
     49 usage(void)
     50 {
     51 	fprint(2, "usage: xshove [window rectangle]\n");
     52 	exits("usage");
     53 }
     54 
     55 void
     56 main(int argc, char **argv)
     57 {
     58 	int screen;
     59 
     60 	screen = 0;
     61 	ARGBEGIN{
     62 	case 's':
     63 		screen = atoi(EARGF(usage()));
     64 		break;
     65 	default:
     66 		usage();
     67 		break;
     68 	}ARGEND
     69 
     70 	dpy = XOpenDisplay("");
     71 	if(dpy == nil)
     72 		sysfatal("open display: %r");
     73 
     74 	root = RootWindow(dpy, screen);
     75 	getinfo();
     76 
     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 }
     86 
     87 char*
     88 getproperty(Window w, Atom a)
     89 {
     90 	uchar *p;
     91 	int fmt;
     92 	Atom type;
     93 	ulong n, dummy;
     94 
     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 }
    104 
    105 Window
    106 findname(Window w)
    107 {
    108 	int i;
    109 	uint nxwin;
    110 	Window dw1, dw2, *xwin;
    111 
    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 }
    121 
    122 void
    123 getinfo(void)
    124 {
    125 	int i;
    126 	uint nxwin;
    127 	Window dw1, dw2, *xwin;
    128 	XClassHint class;
    129 	XWindowAttributes attr;
    130 
    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");
    136 
    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 }
    165 
    166 void
    167 listwindows(void)
    168 {
    169 	int i;
    170 
    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 }
    182 
    183 void
    184 shove(char *name, char *geom)
    185 {
    186 	int i;
    187 	int isdelta, havemin, havesize;
    188 	int old, new;
    189 	Rectangle r;
    190 
    191 	if(parsewinsize(geom, &r, &isdelta, &havemin, &havesize) < 0)
    192 		sysfatal("bad window spec: %s", name);
    193 
    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;
    207 
    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 }
    229 
    230 int
    231 parsewinsize(char *s, Rectangle *r, int *isdelta, int *havemin, int *havesize)
    232 {
    233 	char c, *os;
    234 	int i, j, k, l;
    235 
    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;
    263 
    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 	}
    284 
    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;
    319 
    320 oops:
    321 	werrstr("bad syntax in window size '%s'", os);
    322 	return -1;
    323 }