home *** CD-ROM | disk | FTP | other *** search
/ ftp.freefriends.org / ftp.freefriends.org.tar / ftp.freefriends.org / arnold / Source / 9wm-1.1.shar.gz / 9wm-1.1.shar / manage.c < prev    next >
C/C++ Source or Header  |  1995-01-15  |  10KB  |  471 lines

  1. /* Copyright (c) 1994 David Hogan, see README for licence details */
  2. #include <stdio.h>
  3. #include <X11/X.h>
  4. #include <X11/Xlib.h>
  5. #include <X11/Xutil.h>
  6. #include <X11/Xatom.h>
  7. #include <X11/extensions/shape.h>
  8. #include "dat.h"
  9. #include "fns.h"
  10.  
  11. int
  12. manage(c, mapped)
  13. Client *c;
  14. int mapped;
  15. {
  16.     int fixsize, dohide, doreshape, state;
  17.     long msize;
  18.     XClassHint class;
  19.     XWMHints *hints;
  20.  
  21.     XSelectInput(dpy, c->window, ColormapChangeMask | EnterWindowMask | PropertyChangeMask);
  22.  
  23.     /* Get loads of hints */
  24.  
  25.     if (XGetClassHint(dpy, c->window, &class) != 0) {   /* ``Success'' */
  26.         c->instance = class.res_name;
  27.         c->class = class.res_class;
  28.         c->is9term = (strcmp(c->class, "9term") == 0);
  29.     }
  30.     else {
  31.         c->instance = 0;
  32.         c->class = 0;
  33.         c->is9term = 0;
  34.     }
  35.     c->iconname = getprop(c->window, XA_WM_ICON_NAME);
  36.     c->name = getprop(c->window, XA_WM_NAME);
  37.     setlabel(c);
  38.  
  39.     hints = XGetWMHints(dpy, c->window);
  40.     if (XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
  41.         c->size.flags = PSize;      /* not specified - punt */
  42.  
  43.     getcmaps(c);
  44.     getproto(c);
  45.     gettrans(c);
  46.     if (c->is9term)
  47.         c->hold = getiprop(c->window, _9wm_hold_mode);
  48.  
  49.     /* Figure out what to do with the window from hints */
  50.  
  51.     if (!getstate(c->window, &state))
  52.         state = hints ? hints->initial_state : NormalState;
  53.     dohide = (state == IconicState);
  54.  
  55.     fixsize = 0;
  56.     if ((c->size.flags & (USSize|PSize)))
  57.         fixsize = 1;
  58.     if ((c->size.flags & (PMinSize|PMaxSize)) == PMinSize|PMaxSize && c->size.min_width == c->size.max_width && c->size.min_height == c->size.max_height)
  59.         fixsize = 1;
  60.     doreshape = !mapped;
  61.     if (fixsize) {
  62.         if (c->size.flags & USPosition)
  63.             doreshape = 0;
  64.         if (dohide && (c->size.flags & PPosition))
  65.             doreshape = 0;
  66.         if (c->trans != None)
  67.             doreshape = 0;
  68.     }
  69.     if (c->is9term)
  70.         fixsize = 0;
  71.     if (c->size.flags & PBaseSize) {
  72.         c->min_dx = c->size.base_width;
  73.         c->min_dy = c->size.base_height;
  74.     }
  75.     else if (c->size.flags & PMinSize) {
  76.         c->min_dx = c->size.min_width;
  77.         c->min_dy = c->size.min_height;
  78.     }
  79.     else if (c->is9term) {
  80.         c->min_dx = 100;
  81.         c->min_dy = 50;
  82.     }
  83.     else
  84.         c->min_dx = c->min_dy = 0;
  85.  
  86.     if (hints)
  87.         XFree(hints);
  88.  
  89.     /* Now do it!!! */
  90.  
  91.     if (doreshape) {
  92.         cmapfocus(0);
  93.         if (!(fixsize ? drag(c) : sweep(c)) && c->is9term) {
  94.             XDestroyWindow(dpy, c->window);
  95.             rmclient(c);
  96.             cmapfocus(current);
  97.             return 0;
  98.         }
  99.     }
  100.     else
  101.         gravitate(c, 0);
  102.  
  103.     c->parent = XCreateSimpleWindow(dpy, root,
  104.             c->x - BORDER, c->y - BORDER,
  105.             c->dx + 2*(BORDER-1), c->dy + 2*(BORDER-1),
  106.             1, black, white);
  107.     XSelectInput(dpy, c->parent, SubstructureRedirectMask | SubstructureNotifyMask);
  108.     if (mapped)
  109.         c->reparenting = 1;
  110.     if (doreshape && !fixsize)
  111.         XResizeWindow(dpy, c->window, c->dx, c->dy);
  112.     XSetWindowBorderWidth(dpy, c->window, 0);
  113.     XReparentWindow(dpy, c->window, c->parent, BORDER-1, BORDER-1);
  114. #ifdef  SHAPE
  115.     if (shape) {
  116.         XShapeSelectInput(dpy, c->window, ShapeNotifyMask);
  117.         ignore_badwindow = 1;       /* magic */
  118.         setshape(c);
  119.         ignore_badwindow = 0;
  120.     }
  121. #endif
  122.     XAddToSaveSet(dpy, c->window);
  123.     if (dohide)
  124.         hide(c);
  125.     else {
  126.         XMapWindow(dpy, c->window);
  127.         XMapWindow(dpy, c->parent);
  128.         if (nostalgia || doreshape)
  129.             active(c);
  130.         else if (c->trans != None && current && current->window == c->trans)
  131.             active(c);
  132.         else
  133.             setactive(c, 0);
  134.         setstate(c, NormalState);
  135.     }
  136.     if (current != c)
  137.         cmapfocus(current);
  138.     c->init = 1;
  139.     return 1;
  140. }
  141.  
  142. void
  143. gettrans(c)
  144. Client *c;
  145. {
  146.     Window trans;
  147.  
  148.     trans = None;
  149.     if (XGetTransientForHint(dpy, c->window, &trans) != 0)
  150.         c->trans = trans;
  151.     else
  152.         c->trans = None;
  153. }
  154.  
  155. void
  156. withdraw(c)
  157. Client *c;
  158. {
  159.     XUnmapWindow(dpy, c->parent);
  160.     gravitate(c, 1);
  161.     XReparentWindow(dpy, c->window, root, c->x, c->y);
  162.     gravitate(c, 0);
  163.     XRemoveFromSaveSet(dpy, c->window);
  164.     setstate(c, WithdrawnState);
  165.  
  166.     /* flush any errors */
  167.     ignore_badwindow = 1;
  168.     XSync(dpy, False);
  169.     ignore_badwindow = 0;
  170. }
  171.  
  172. void
  173. gravitate(c, invert)
  174. Client *c;
  175. int invert;
  176. {
  177.     int gravity, dx, dy, delta;
  178.  
  179.     gravity = NorthWestGravity;
  180.     if (c->size.flags & PWinGravity)
  181.         gravity = c->size.win_gravity;
  182.  
  183.     delta = c->border-BORDER;
  184.     switch (gravity) {
  185.     case NorthWestGravity:
  186.         dx = 0;
  187.         dy = 0;
  188.         break;
  189.     case NorthGravity:
  190.         dx = delta;
  191.         dy = 0;
  192.         break;
  193.     case NorthEastGravity:
  194.         dx = 2*delta;
  195.         dy = 0;
  196.         break;
  197.     case WestGravity:
  198.         dx = 0;
  199.         dy = delta;
  200.         break;
  201.     case CenterGravity:
  202.     case StaticGravity:
  203.         dx = delta;
  204.         dy = delta;
  205.         break;
  206.     case EastGravity:
  207.         dx = 2*delta;
  208.         dy = delta;
  209.         break;
  210.     case SouthWestGravity:
  211.         dx = 0;
  212.         dy = 2*delta;
  213.         break;
  214.     case SouthGravity:
  215.         dx = delta;
  216.         dy = 2*delta;
  217.         break;
  218.     case SouthEastGravity:
  219.         dx = 2*delta;
  220.         dy = 2*delta;
  221.         break;
  222.     default:
  223.         fprintf(stderr, "9wm: bad window gravity %d for 0x%x\n", gravity, c->window);
  224.     }
  225.     dx += BORDER;
  226.     dy += BORDER;
  227.     if (invert) {
  228.         dx = -dx;
  229.         dy = -dy;
  230.     }
  231.     c->x += dx;
  232.     c->y += dy;
  233. }
  234.  
  235. void
  236. cleanup()
  237. {
  238.     Client *c;
  239.     XWindowChanges wc;
  240.  
  241.     for (c = clients; c; c = c->next) {
  242.         gravitate(c, 1);
  243.         XReparentWindow(dpy, c->window, root, c->x, c->y);
  244.         wc.border_width = c->border;
  245.         XConfigureWindow(dpy, c->window, CWBorderWidth, &wc);
  246.     }
  247.     XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, timestamp());
  248.     cmapfocus(0);
  249.     XCloseDisplay(dpy);
  250. }
  251.  
  252. static void
  253. installcmap(cmap)
  254. Colormap cmap;
  255. {
  256.     XInstallColormap(dpy, (cmap == None) ? def_cmap : cmap);
  257. }
  258.  
  259. void
  260. cmapfocus(c)
  261. Client *c;
  262. {
  263.     int i, found;
  264.     Client *cc;
  265.  
  266.     if (c == 0)
  267.         installcmap(None);
  268.     else if (c->ncmapwins != 0) {
  269.         found = 0;
  270.         for (i = c->ncmapwins-1; i >= 0; i--) {
  271.             installcmap(c->wmcmaps[i]);
  272.             if (c->cmapwins[i] == c->window)
  273.                 found++;
  274.         }
  275.         if (!found)
  276.             installcmap(c->cmap);
  277.     }
  278.     else if (c->trans != None && (cc = getclient(c->trans, 0)) != 0 && cc->ncmapwins != 0)
  279.         cmapfocus(cc);
  280.     else
  281.         installcmap(c->cmap);
  282. }
  283.  
  284. void
  285. getcmaps(c)
  286. Client *c;
  287. {
  288.     int n, i;
  289.     Window *cw;
  290.     XWindowAttributes attr;
  291.  
  292.     if (!c->init) {
  293.         XGetWindowAttributes(dpy, c->window, &attr);
  294.         c->cmap = attr.colormap;
  295.     }
  296.  
  297.     n = _getprop(c->window, wm_colormaps, XA_WINDOW, 100L, (unsigned char **)&cw);
  298.     if (c->ncmapwins != 0) {
  299.         XFree((char *)c->cmapwins);
  300.         free((char *)c->wmcmaps);
  301.     }
  302.     if (n <= 0) {
  303.         c->ncmapwins = 0;
  304.         return;
  305.     }
  306.  
  307.     c->ncmapwins = n;
  308.     c->cmapwins = cw;
  309.  
  310.     c->wmcmaps = (Colormap*)malloc(n*sizeof(Colormap));
  311.     for (i = 0; i < n; i++) {
  312.         if (cw[i] == c->window)
  313.             c->wmcmaps[i] = c->cmap;
  314.         else {
  315.             XSelectInput(dpy, cw[i], ColormapChangeMask);
  316.             XGetWindowAttributes(dpy, cw[i], &attr);
  317.             c->wmcmaps[i] = attr.colormap;
  318.         }
  319.     }
  320. }
  321.  
  322. void
  323. setlabel(c)
  324. Client *c;
  325. {
  326.     if (c->iconname != 0)
  327.         c->label = c->iconname;
  328.     else if (c->name != 0)
  329.         c->label = c->name;
  330.     else if (c->instance != 0)
  331.         c->label = c->instance;
  332.     else
  333.         c->label = "<unlabelled>";
  334. }
  335.  
  336. #ifdef  SHAPE
  337. void
  338. setshape(c)
  339. Client *c;
  340. {
  341.     int n, order;
  342.     XRectangle *rect;
  343.  
  344.     /* cheat: don't try to add a border if the window is non-rectangular */
  345.     rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order);
  346.     if (n > 1)
  347.         XShapeCombineShape(dpy, c->parent, ShapeBounding, BORDER-1, BORDER-1,
  348.             c->window, ShapeBounding, ShapeSet);
  349.     XFree((void*)rect);
  350. }
  351. #endif
  352.  
  353. int
  354. _getprop(w, a, type, len, p)
  355. Window w;
  356. Atom a;
  357. Atom type;
  358. long len;       /* in 32-bit multiples... */
  359. unsigned char **p;
  360. {
  361.     Atom real_type;
  362.     int format;
  363.     unsigned long n, extra;
  364.     int status;
  365.  
  366.     status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p);
  367.     if (status != Success || *p == 0)
  368.         return -1;
  369.     if (n == 0)
  370.         XFree((void*) *p);
  371.     /* could check real_type, format, extra here... */
  372.     return n;
  373. }
  374.  
  375. char *
  376. getprop(w, a)
  377. Window w;
  378. Atom a;
  379. {
  380.     unsigned char *p;
  381.     int n;
  382.  
  383.     if (_getprop(w, a, XA_STRING, 100L, &p) <= 0)
  384.         return 0;
  385.     return (char *)p;
  386. }
  387.  
  388. int
  389. get1prop(w, a, type)
  390. Window w;
  391. Atom a;
  392. Atom type;
  393. {
  394.     char **p, *x;
  395.  
  396.     if (_getprop(w, a, type, 1L, &p) <= 0)
  397.         return 0;
  398.     x = *p;
  399.     XFree((void*) p);
  400.     return (int)x;
  401. }
  402.  
  403. Window
  404. getwprop(w, a)
  405. Window w;
  406. Atom a;
  407. {
  408.     return get1prop(w, a, XA_WINDOW);
  409. }
  410.  
  411. int
  412. getiprop(w, a)
  413. Window w;
  414. Atom a;
  415. {
  416.     return get1prop(w, a, XA_INTEGER);
  417. }
  418.  
  419. void
  420. setstate(c, state)
  421. Client *c;
  422. int state;
  423. {
  424.     long data[2];
  425.  
  426.     data[0] = (long) state;
  427.     data[1] = (long) None;
  428.  
  429.     c->state = state;
  430.     XChangeProperty(dpy, c->window, wm_state, wm_state, 32,
  431.         PropModeReplace, (unsigned char *)data, 2);
  432. }
  433.  
  434. int
  435. getstate(w, state)
  436. Window w;
  437. int *state;
  438. {
  439.     long *p = 0;
  440.  
  441.     if (_getprop(w, wm_state, wm_state, 2L, (char**)&p) <= 0)
  442.         return 0;
  443.  
  444.     *state = (int) *p;
  445.     XFree((char *) p);
  446.     return 1;
  447. }
  448.  
  449. void
  450. getproto(c)
  451. Client *c;
  452. {
  453.     Atom *p;
  454.     int i;
  455.     long n;
  456.     Window w;
  457.  
  458.     w = c->window;
  459.     c->proto = 0;
  460.     if ((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (char**)&p)) <= 0)
  461.         return;
  462.  
  463.     for (i = 0; i < n; i++)
  464.         if (p[i] == wm_delete)
  465.             c->proto |= Pdelete;
  466.         else if (p[i] == wm_take_focus)
  467.             c->proto |= Ptakefocus;
  468.  
  469.     XFree((char *) p);
  470. }
  471.