Commit Diff


commit - 9daa3ca74ebd673d00ba52667c50fe4a0046d100
commit + f73497bbafecbedd367eaab16aaf37c701672be0
blob - 135226d3aee91e9aaf796ef94bd63cd7de7974fc
blob + e542686540a72abe019973fa5ee08b7cf5a58785
--- src/cmd/rio/mkfile
+++ src/cmd/rio/mkfile
@@ -1,7 +1,7 @@
 <$PLAN9/src/mkhdr
 <|sh ../devdraw/mkwsysrules.sh	# for X11
 
-OFILES=\
+RIOFILES=\
 	client.$O\
 	color.$O\
 	cursor.$O\
@@ -16,7 +16,7 @@ OFILES=\
 CFLAGS=$CFLAGS -DDEBUG
 HFILES=dat.h fns.h
 
-TARG=rio
+TARG=rio xshove
 
 # need to add lib64 when it exists (on x86-64), but
 # Darwin complains about the nonexistant directory
@@ -27,6 +27,8 @@ LDFLAGS=-L$X11/lib$L64/ -lXext -lX11
 
 <|sh mkriorules.sh
 
+$O.rio: $RIOFILES
+
 CFLAGS=$CFLAGS -DSHAPE -DDEBUG_EV -DDEBUG
 
 $O.xevents: xevents.$O printevent.$O
@@ -35,3 +37,7 @@ $O.xevents: xevents.$O printevent.$O
 xevents.$O printevent.$O: printevent.h
 
 error.$O: showevent/ShowEvent.c
+
+$O.xshove: xshove.$O
+	$LD -o $O.xshove xshove.$O -lX11
+
blob - 0b25d2e22b0021cf975dd0b5b56c0106c302ce88
blob + 6918d9914274b15d7c44f4f7b90bedba15e1c7db
--- src/cmd/rio/mkriorules.sh
+++ src/cmd/rio/mkriorules.sh
@@ -3,4 +3,4 @@ if [ "x$WSYSTYPE" = xnowsys ]; then
 	echo '	#'
 	exit 0
 fi
-cat $PLAN9/src/mkone
\ No newline at end of file
+cat $PLAN9/src/mkmany
blob - /dev/null
blob + e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 (mode 644)
blob - /dev/null
blob + 1b1c7fa5c87b75bfeabe8632cfa4a448b7324189 (mode 644)
--- /dev/null
+++ src/cmd/rio/xshove.c
@@ -0,0 +1,289 @@
+#include <u.h>
+#include <X11/X.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <libc.h>
+#include <ctype.h>
+
+AUTOLIB(X11);
+
+typedef struct Rectangle Rectangle;
+struct Rectangle
+{
+	struct {
+		int x;
+		int y;
+	} min, max;
+};
+#define Dx(r) ((r).max.x - (r).min.x)
+#define Dy(r) ((r).max.y - (r).min.y)
+
+typedef struct Win Win;
+struct Win
+{
+	Window xw;
+	int x;
+	int y;
+	int dx;
+	int dy;
+	char *class;
+	char *instance;
+	char *name;
+	char *iconname;
+};
+
+Display *dpy;
+Window root;
+
+Win *w;
+int nw;
+
+void getinfo(void);
+void listwindows(void);
+int parsewinsize(char*, Rectangle*, int*);
+void shove(char*, char*);
+
+void
+usage(void)
+{
+	fprint(2, "usage: xshove window rectangle\n"
+	          "   or  xshove\n"
+	          "window can be a window ID or a program name\n"
+	          "rectangle is a p9p window spec (see intro(1))\n");
+	exits("usage");
+}
+
+void
+main(int argc, char **argv)
+{
+	int screen;
+	
+	screen = 0;
+	ARGBEGIN{
+	case 's':
+		screen = atoi(EARGF(usage()));
+		break;
+	default:
+		usage();
+		break;
+	}ARGEND
+	
+	dpy = XOpenDisplay("");
+	if(dpy == nil)
+		sysfatal("open display: %r");
+
+	root = RootWindow(dpy, screen);
+	getinfo();
+
+	if(argc == 0){
+		listwindows();
+		exits(0);
+	}
+	if(argc != 2)
+		usage();
+	shove(argv[0], argv[1]);
+	exits(0);
+}
+
+char*
+getproperty(Window w, Atom a)
+{
+	uchar *p;
+	int fmt;
+	Atom type;
+	ulong n, dummy;
+
+	n = 100;
+	p = nil;
+	XGetWindowProperty(dpy, w, a, 0, 100L, 0, 
+		AnyPropertyType, &type, &fmt,
+		&n, &dummy, &p);
+	if(p == nil || *p == 0)
+		return nil;
+	return strdup((char*)p);
+}
+
+Window
+findname(Window w)
+{
+	int i;
+	uint nxwin;
+	Window dw1, dw2, *xwin;
+
+	if(getproperty(w, XA_WM_NAME))
+		return w;
+	if(!XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin))
+		return 0;
+	for(i=0; i<nxwin; i++)
+		if((w = findname(xwin[i])) != 0)
+			return w;
+	return 0;
+}
+
+void
+getinfo(void)
+{
+	int i;
+	uint nxwin;
+	Window dw1, dw2, *xwin;
+	XClassHint class;
+	XWindowAttributes attr;
+
+	if(!XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin))
+		return;
+	w = mallocz(nxwin*sizeof w[0], 1);
+	if(w == 0)
+		sysfatal("malloc: %r");
+	
+	Win *ww = w;
+	for(i=0; i<nxwin; i++){
+		memset(&attr, 0, sizeof attr);
+		xwin[i] = findname(xwin[i]);
+		if(xwin[i] == 0)
+			continue;
+		XGetWindowAttributes(dpy, xwin[i], &attr);
+		if(attr.width <= 0 || attr.override_redirect || attr.map_state != IsViewable)
+			continue;
+		ww->xw = xwin[i];
+		ww->x = attr.x;
+		ww->y = attr.y;
+		ww->dx = attr.width;
+		ww->dy = attr.height;
+		XTranslateCoordinates(dpy, ww->xw, root, 0, 0, &ww->x, &ww->y, &dw1);
+		if(XGetClassHint(dpy, ww->xw, &class)){
+			ww->class = strdup(class.res_class);
+			ww->instance = strdup(class.res_name);
+		}
+		ww->iconname = getproperty(ww->xw, XA_WM_ICON_NAME);
+		ww->name = getproperty(ww->xw, XA_WM_NAME);
+		ww++;
+	}
+	nw = ww - w;
+}		
+
+void
+listwindows(void)
+{
+	int i;
+
+	for(i=0; i<nw; i++){
+		Win *ww = &w[i];
+		char rect[50];
+		snprint(rect, sizeof rect, "%d,%d,%d,%d", ww->x, ww->y, ww->x+ww->dx, ww->y+ww->dy);
+		print("%08x %-20s %-10s %s\n",
+			(uint)ww->xw, 
+			rect,
+			ww->instance,
+			ww->class);
+	}
+}
+
+void
+shove(char *name, char *geom)
+{
+	int i;
+	int havemin;
+	Rectangle r;
+
+	if(parsewinsize(geom, &r, &havemin) < 0)
+		sysfatal("bad window spec: %s", name);
+
+	for(i=0; i<nw; i++){
+		Win *ww = &w[i];
+		if(ww->instance && strstr(ww->instance, name)
+		   || ww->class && strstr(ww->class, name)){
+			int value_mask;
+			XWindowChanges e;
+
+			memset(&e, 0, sizeof e);
+			e.width = Dx(r);
+			e.height = Dy(r);
+			value_mask = CWWidth | CWHeight;
+			if(havemin){
+				e.x = r.min.x;
+				e.y = r.min.y;
+				value_mask |= CWX | CWY;
+			}
+			XConfigureWindow(dpy, ww->xw, value_mask, &e);
+			XFlush(dpy);
+		}
+	}
+}
+
+int
+parsewinsize(char *s, Rectangle *r, int *havemin)
+{
+	char c, *os;
+	int i, j, k, l;
+
+	os = s;
+	*havemin = 0;
+	memset(r, 0, sizeof *r);
+	if(!isdigit((uchar)*s))
+		goto oops;
+	i = strtol(s, &s, 0);
+	if(*s == 'x'){
+		s++;
+		if(!isdigit((uchar)*s))
+			goto oops;
+		j = strtol(s, &s, 0);
+		r->max.x = i;
+		r->max.y = j;
+		if(*s == 0)
+			return 0;
+		if(*s != '@')
+			goto oops;
+
+		s++;
+		if(!isdigit((uchar)*s))
+			goto oops;
+		i = strtol(s, &s, 0);
+		if(*s != ',' && *s != ' ')
+			goto oops;
+		s++;
+		if(!isdigit((uchar)*s))
+			goto oops;
+		j = strtol(s, &s, 0);
+		if(*s != 0)
+			goto oops;
+		r->min.x += i;
+		r->max.x += i;
+		r->min.y += j;
+		r->max.y += j;
+		*havemin = 1;
+		return 0;
+	}
+
+	c = *s;
+	if(c != ' ' && c != ',')
+		goto oops;
+	s++;
+	if(!isdigit((uchar)*s))
+		goto oops;
+	j = strtol(s, &s, 0);
+	if(*s != c)
+		goto oops;
+	s++;
+	if(!isdigit((uchar)*s))
+		goto oops;
+	k = strtol(s, &s, 0);
+	if(*s != c)
+		goto oops;
+	s++;
+	if(!isdigit((uchar)*s))
+		goto oops;
+	l = strtol(s, &s, 0);
+	if(*s != 0)
+		goto oops;
+	r->min.x = i;
+	r->min.y = j;
+	r->max.x = k;
+	r->max.y = l;
+	*havemin = 1;
+	return 0;
+
+oops:
+	werrstr("bad syntax in window size '%s'", os);
+	return -1;
+}