diff options
author | rsc <devnull@localhost> | 2004-03-21 04:27:28 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-03-21 04:27:28 +0000 |
commit | 038e9089b354385cada2a35663c863d43dd5b20d (patch) | |
tree | 029fadfc751f82e693daef7a66bc22c87e85479c /src/cmd/rio/manage.c | |
parent | ba9ffa53c4825e115078ed098205d75aa7a77eb0 (diff) | |
download | plan9port-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.c | 482 |
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); +} |