aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/rio/manage.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-03-21 04:27:28 +0000
committerrsc <devnull@localhost>2004-03-21 04:27:28 +0000
commit038e9089b354385cada2a35663c863d43dd5b20d (patch)
tree029fadfc751f82e693daef7a66bc22c87e85479c /src/cmd/rio/manage.c
parentba9ffa53c4825e115078ed098205d75aa7a77eb0 (diff)
downloadplan9port-038e9089b354385cada2a35663c863d43dd5b20d.tar.gz
plan9port-038e9089b354385cada2a35663c863d43dd5b20d.tar.bz2
plan9port-038e9089b354385cada2a35663c863d43dd5b20d.zip
Change 9wm to look like rio.
Diffstat (limited to 'src/cmd/rio/manage.c')
-rw-r--r--src/cmd/rio/manage.c482
1 files changed, 482 insertions, 0 deletions
diff --git a/src/cmd/rio/manage.c b/src/cmd/rio/manage.c
new file mode 100644
index 00000000..3384daf2
--- /dev/null
+++ b/src/cmd/rio/manage.c
@@ -0,0 +1,482 @@
+/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/shape.h>
+#include "dat.h"
+#include "fns.h"
+
+int
+manage(Client *c, int mapped)
+{
+ int fixsize, dohide, doreshape, state;
+ long msize;
+ XClassHint class;
+ XWMHints *hints;
+
+ trace("manage", c, 0);
+ XSelectInput(dpy, c->window, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | FocusChangeMask);
+
+ /* Get loads of hints */
+
+ if (XGetClassHint(dpy, c->window, &class) != 0) { /* ``Success'' */
+ c->instance = class.res_name;
+ c->class = class.res_class;
+ c->is9term = (strcmp(c->class, "9term") == 0);
+ }
+ else {
+ c->instance = 0;
+ c->class = 0;
+ c->is9term = 0;
+ }
+ c->iconname = getprop(c->window, XA_WM_ICON_NAME);
+ c->name = getprop(c->window, XA_WM_NAME);
+ setlabel(c);
+
+ hints = XGetWMHints(dpy, c->window);
+ if (XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
+ c->size.flags = PSize; /* not specified - punt */
+
+ getcmaps(c);
+ getproto(c);
+ gettrans(c);
+ if (c->is9term)
+ c->hold = getiprop(c->window, _9wm_hold_mode);
+
+ /* Figure out what to do with the window from hints */
+
+ if (!getstate(c->window, &state))
+ state = hints ? hints->initial_state : NormalState;
+ dohide = (state == IconicState);
+
+ fixsize = 0;
+ if ((c->size.flags & (USSize|PSize)))
+ fixsize = 1;
+ if ((c->size.flags & (PMinSize|PMaxSize)) == (PMinSize|PMaxSize) && c->size.min_width == c->size.max_width && c->size.min_height == c->size.max_height)
+ fixsize = 1;
+ doreshape = !mapped;
+ if (fixsize) {
+ if (c->size.flags & USPosition)
+ doreshape = 0;
+ if (dohide && (c->size.flags & PPosition))
+ doreshape = 0;
+ if (c->trans != None)
+ doreshape = 0;
+ }
+ if (c->is9term)
+ fixsize = 0;
+ if (c->size.flags & PBaseSize) {
+ c->min_dx = c->size.base_width;
+ c->min_dy = c->size.base_height;
+ }
+ else if (c->size.flags & PMinSize) {
+ c->min_dx = c->size.min_width;
+ c->min_dy = c->size.min_height;
+ }
+ else if (c->is9term) {
+ c->min_dx = 100;
+ c->min_dy = 50;
+ }
+ else
+ c->min_dx = c->min_dy = 0;
+
+ if (hints)
+ XFree(hints);
+
+ /* Now do it!!! */
+
+ if (doreshape) {
+ if (current && current->screen == c->screen)
+ cmapnofocus(c->screen);
+ if (!c->is9term && c->x==0 && c->y==0) {
+ static int nwin;
+
+ c->x = 20*nwin+BORDER;
+ c->y = 20*nwin+BORDER;
+ nwin++;
+ nwin %= 10;
+ }
+
+ if (c->is9term && !(fixsize ? drag(c) : sweep(c))) {
+ XKillClient(dpy, c->window);
+ rmclient(c);
+ if (current && current->screen == c->screen)
+ cmapfocus(current);
+ return 0;
+ }
+ }
+ else
+ gravitate(c, 0);
+
+ c->parent = XCreateSimpleWindow(dpy, c->screen->root,
+ c->x - BORDER, c->y - BORDER,
+ c->dx + 2*BORDER, c->dy + 2*BORDER,
+ 0, c->screen->black, c->screen->white);
+ XSelectInput(dpy, c->parent, SubstructureRedirectMask | SubstructureNotifyMask);
+ if (mapped)
+ c->reparenting = 1;
+ if (doreshape && !fixsize)
+ XResizeWindow(dpy, c->window, c->dx, c->dy);
+ XSetWindowBorderWidth(dpy, c->window, 0);
+ XReparentWindow(dpy, c->window, c->parent, BORDER, BORDER);
+#ifdef SHAPE
+ if (shape) {
+ XShapeSelectInput(dpy, c->window, ShapeNotifyMask);
+ ignore_badwindow = 1; /* magic */
+ setshape(c);
+ ignore_badwindow = 0;
+ }
+#endif
+ XAddToSaveSet(dpy, c->window);
+ if (dohide)
+ hide(c);
+ else {
+ XMapWindow(dpy, c->window);
+ XMapWindow(dpy, c->parent);
+ XUnmapWindow(dpy, c->screen->sweepwin);
+ if (nostalgia || doreshape)
+ active(c);
+ else if (c->trans != None && current && current->window == c->trans)
+ active(c);
+ else
+ setactive(c, 0);
+ setstate(c, NormalState);
+ }
+ if (current && (current != c))
+ cmapfocus(current);
+ c->init = 1;
+ return 1;
+}
+
+void
+scanwins(ScreenInfo *s)
+{
+ unsigned int i, nwins;
+ Client *c;
+ Window dw1, dw2, *wins;
+ XWindowAttributes attr;
+
+ XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins);
+ for (i = 0; i < nwins; i++) {
+ XGetWindowAttributes(dpy, wins[i], &attr);
+ if (attr.override_redirect || wins[i] == s->menuwin)
+ continue;
+ c = getclient(wins[i], 1);
+ if (c != 0 && c->window == wins[i] && !c->init) {
+ c->x = attr.x;
+ c->y = attr.y;
+ c->dx = attr.width;
+ c->dy = attr.height;
+ c->border = attr.border_width;
+ c->screen = s;
+ c->parent = s->root;
+ if (attr.map_state == IsViewable)
+ manage(c, 1);
+ }
+ }
+ XFree((void *) wins); /* cast is to shut stoopid compiler up */
+}
+
+void
+gettrans(Client *c)
+{
+ Window trans;
+
+ trans = None;
+ if (XGetTransientForHint(dpy, c->window, &trans) != 0)
+ c->trans = trans;
+ else
+ c->trans = None;
+}
+
+void
+withdraw(Client *c)
+{
+ XUnmapWindow(dpy, c->parent);
+ gravitate(c, 1);
+ XReparentWindow(dpy, c->window, c->screen->root, c->x, c->y);
+ gravitate(c, 0);
+ XRemoveFromSaveSet(dpy, c->window);
+ setstate(c, WithdrawnState);
+
+ /* flush any errors */
+ ignore_badwindow = 1;
+ XSync(dpy, False);
+ ignore_badwindow = 0;
+}
+
+void
+gravitate(Client *c, int invert)
+{
+ int gravity, dx, dy, delta;
+
+ gravity = NorthWestGravity;
+ if (c->size.flags & PWinGravity)
+ gravity = c->size.win_gravity;
+
+ delta = c->border-BORDER;
+ switch (gravity) {
+ case NorthWestGravity:
+ dx = 0;
+ dy = 0;
+ break;
+ case NorthGravity:
+ dx = delta;
+ dy = 0;
+ break;
+ case NorthEastGravity:
+ dx = 2*delta;
+ dy = 0;
+ break;
+ case WestGravity:
+ dx = 0;
+ dy = delta;
+ break;
+ case CenterGravity:
+ case StaticGravity:
+ dx = delta;
+ dy = delta;
+ break;
+ case EastGravity:
+ dx = 2*delta;
+ dy = delta;
+ break;
+ case SouthWestGravity:
+ dx = 0;
+ dy = 2*delta;
+ break;
+ case SouthGravity:
+ dx = delta;
+ dy = 2*delta;
+ break;
+ case SouthEastGravity:
+ dx = 2*delta;
+ dy = 2*delta;
+ break;
+ default:
+ fprintf(stderr, "9wm: bad window gravity %d for 0x%x\n", gravity, c->window);
+ return;
+ }
+ dx += BORDER;
+ dy += BORDER;
+ if (invert) {
+ dx = -dx;
+ dy = -dy;
+ }
+ c->x += dx;
+ c->y += dy;
+}
+
+static void
+installcmap(ScreenInfo *s, Colormap cmap)
+{
+ if (cmap == None)
+ XInstallColormap(dpy, s->def_cmap);
+ else
+ XInstallColormap(dpy, cmap);
+}
+
+void
+cmapfocus(Client *c)
+{
+ int i, found;
+ Client *cc;
+
+ if (c == 0)
+ return;
+ else if (c->ncmapwins != 0) {
+ found = 0;
+ for (i = c->ncmapwins-1; i >= 0; i--) {
+ installcmap(c->screen, c->wmcmaps[i]);
+ if (c->cmapwins[i] == c->window)
+ found++;
+ }
+ if (!found)
+ installcmap(c->screen, c->cmap);
+ }
+ else if (c->trans != None && (cc = getclient(c->trans, 0)) != 0 && cc->ncmapwins != 0)
+ cmapfocus(cc);
+ else
+ installcmap(c->screen, c->cmap);
+}
+
+void
+cmapnofocus(ScreenInfo *s)
+{
+ installcmap(s, None);
+}
+
+void
+getcmaps(Client *c)
+{
+ int n, i;
+ Window *cw;
+ XWindowAttributes attr;
+
+ if (!c->init) {
+ XGetWindowAttributes(dpy, c->window, &attr);
+ c->cmap = attr.colormap;
+ }
+
+ n = _getprop(c->window, wm_colormaps, XA_WINDOW, 100L, (unsigned char **)&cw);
+ if (c->ncmapwins != 0) {
+ XFree((char *)c->cmapwins);
+ free((char *)c->wmcmaps);
+ }
+ if (n <= 0) {
+ c->ncmapwins = 0;
+ return;
+ }
+
+ c->ncmapwins = n;
+ c->cmapwins = cw;
+
+ c->wmcmaps = (Colormap*)malloc(n*sizeof(Colormap));
+ for (i = 0; i < n; i++) {
+ if (cw[i] == c->window)
+ c->wmcmaps[i] = c->cmap;
+ else {
+ XSelectInput(dpy, cw[i], ColormapChangeMask);
+ XGetWindowAttributes(dpy, cw[i], &attr);
+ c->wmcmaps[i] = attr.colormap;
+ }
+ }
+}
+
+void
+setlabel(Client *c)
+{
+ char *label, *p;
+
+ if (c->iconname != 0)
+ label = c->iconname;
+ else if (c->name != 0)
+ label = c->name;
+ else if (c->instance != 0)
+ label = c->instance;
+ else if (c->class != 0)
+ label = c->class;
+ else
+ label = "no label";
+ if ((p = index(label, ':')) != 0)
+ *p = '\0';
+ c->label = label;
+}
+
+#ifdef SHAPE
+void
+setshape(Client *c)
+{
+ int n, order;
+ XRectangle *rect;
+
+ /* don't try to add a border if the window is non-rectangular */
+ rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order);
+ if (n > 1)
+ XShapeCombineShape(dpy, c->parent, ShapeBounding, BORDER, BORDER,
+ c->window, ShapeBounding, ShapeSet);
+ XFree((void*)rect);
+}
+#endif
+
+int
+_getprop(Window w, Atom a, Atom type, long len, unsigned char **p)
+{
+ Atom real_type;
+ int format;
+ unsigned long n, extra;
+ int status;
+
+ status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p);
+ if (status != Success || *p == 0)
+ return -1;
+ if (n == 0)
+ XFree((void*) *p);
+ /* could check real_type, format, extra here... */
+ return n;
+}
+
+char *
+getprop(Window w, Atom a)
+{
+ unsigned char *p;
+
+ if (_getprop(w, a, XA_STRING, 100L, &p) <= 0)
+ return 0;
+ return (char *)p;
+}
+
+int
+get1prop(Window w, Atom a, Atom type)
+{
+ char **p, *x;
+
+ if (_getprop(w, a, type, 1L, (unsigned char**)&p) <= 0)
+ return 0;
+ x = *p;
+ XFree((void*) p);
+ return (int)x;
+}
+
+Window
+getwprop(Window w, Atom a)
+{
+ return get1prop(w, a, XA_WINDOW);
+}
+
+int
+getiprop(Window w, Atom a)
+{
+ return get1prop(w, a, XA_INTEGER);
+}
+
+void
+setstate(Client *c, int state)
+{
+ long data[2];
+
+ data[0] = (long) state;
+ data[1] = (long) None;
+
+ c->state = state;
+ XChangeProperty(dpy, c->window, wm_state, wm_state, 32,
+ PropModeReplace, (unsigned char *)data, 2);
+}
+
+int
+getstate(Window w, int *state)
+{
+ long *p = 0;
+
+ if (_getprop(w, wm_state, wm_state, 2L, (unsigned char**)&p) <= 0)
+ return 0;
+
+ *state = (int) *p;
+ XFree((char *) p);
+ return 1;
+}
+
+void
+getproto(Client *c)
+{
+ Atom *p;
+ int i;
+ long n;
+ Window w;
+
+ w = c->window;
+ c->proto = 0;
+ if ((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (unsigned char**)&p)) <= 0)
+ return;
+
+ for (i = 0; i < n; i++)
+ if (p[i] == wm_delete)
+ c->proto |= Pdelete;
+ else if (p[i] == wm_take_focus)
+ c->proto |= Ptakefocus;
+
+ XFree((char *) p);
+}