URI:
       txshove.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       txshove.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 }