9wm-1.2.orig/ 40700 1755 1750 0 6224754311 11174 5ustar krsusers9wm-1.2.orig/client.c100600 1755 1750 10751 6224754220 12740 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include "dat.h" #include "fns.h" Client *clients; Client *current; void setactive(c, on) Client *c; int on; { if (c->parent == c->screen->root) { fprintf(stderr, "9wm: bad parent in setactive; dumping core\n"); abort(); } if (on) { XUngrabButton(dpy, AnyButton, AnyModifier, c->parent); XSetInputFocus(dpy, c->window, RevertToPointerRoot, timestamp()); if (c->proto & Ptakefocus) sendcmessage(c->window, wm_protocols, wm_take_focus, 0); cmapfocus(c); } else XGrabButton(dpy, AnyButton, AnyModifier, c->parent, False, ButtonMask, GrabModeAsync, GrabModeSync, None, None); draw_border(c, on); } void draw_border(c, active) Client *c; int active; { XSetWindowBackground(dpy, c->parent, active ? c->screen->black : c->screen->white); XClearWindow(dpy, c->parent); if (c->hold && active) XDrawRectangle(dpy, c->parent, c->screen->gc, INSET, INSET, c->dx+BORDER-INSET, c->dy+BORDER-INSET); } void active(c) Client *c; { Client *cc; if (c == 0) { fprintf(stderr, "9wm: active(c==0)\n"); return; } if (c == current) return; if (current) { setactive(current, 0); if (current->screen != c->screen) cmapnofocus(current->screen); } setactive(c, 1); for (cc = clients; cc; cc = cc->next) if (cc->revert == c) cc->revert = c->revert; c->revert = current; while (c->revert && !normal(c->revert)) c->revert = c->revert->revert; current = c; #ifdef DEBUG if (debug) dump_revert(); #endif } void nofocus() { static Window w = 0; int mask; XSetWindowAttributes attr; Client *c; if (current) { setactive(current, 0); for (c = current->revert; c; c = c->revert) if (normal(c)) { active(c); return; } cmapnofocus(current->screen); /* if no candidates to revert to, fall through */ } current = 0; if (w == 0) { mask = CWOverrideRedirect; attr.override_redirect = 1; w = XCreateWindow(dpy, screens[0].root, 0, 0, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, mask, &attr); XMapWindow(dpy, w); } XSetInputFocus(dpy, w, RevertToPointerRoot, timestamp()); } void top(c) Client *c; { Client **l, *cc; l = &clients; for (cc = *l; cc; cc = *l) { if (cc == c) { *l = c->next; c->next = clients; clients = c; return; } l = &cc->next; } fprintf(stderr, "9wm: %x not on client list in top()\n", c); } Client * getclient(w, create) Window w; int create; { Client *c; if (w == 0 || getscreen(w)) return 0; for (c = clients; c; c = c->next) if (c->window == w || c->parent == w) return c; if (!create) return 0; c = (Client *)malloc(sizeof(Client)); memset(c, 0, sizeof(Client)); c->window = w; /* c->parent will be set by the caller */ c->parent = None; c->reparenting = 0; c->state = WithdrawnState; c->init = 0; c->cmap = None; c->label = c->class = 0; c->revert = 0; c->is9term = 0; c->hold = 0; c->ncmapwins = 0; c->cmapwins = 0; c->wmcmaps = 0; c->next = clients; clients = c; return c; } void rmclient(c) Client *c; { Client *cc; for (cc = current; cc && cc->revert; cc = cc->revert) if (cc->revert == c) cc->revert = cc->revert->revert; if (c == clients) clients = c->next; for (cc = clients; cc && cc->next; cc = cc->next) if (cc->next == c) cc->next = cc->next->next; if (hidden(c)) unhidec(c, 0); if (c->parent != c->screen->root) XDestroyWindow(dpy, c->parent); c->parent = c->window = None; /* paranoia */ if (current == c) { current = c->revert; if (current == 0) nofocus(); else { if (current->screen != c->screen) cmapnofocus(c->screen); setactive(current, 1); } } if (c->ncmapwins != 0) { XFree((char *)c->cmapwins); free((char *)c->wmcmaps); } if (c->iconname != 0) XFree((char*) c->iconname); if (c->name != 0) XFree((char*) c->name); if (c->instance != 0) XFree((char*) c->instance); if (c->class != 0) XFree((char*) c->class); memset(c, 0, sizeof(Client)); /* paranoia */ free(c); } #ifdef DEBUG void dump_revert() { Client *c; int i; i = 0; for (c = current; c; c = c->revert) { fprintf(stderr, "%s(%x:%d)", c->label ? c->label : "?", c->window, c->state); if (i++ > 100) break; if (c->revert) fprintf(stderr, " -> "); } if (current == 0) fprintf(stderr, "empty"); fprintf(stderr, "\n"); } void dump_clients() { Client *c; for (c = clients; c; c = c->next) fprintf(stderr, "w 0x%x parent 0x%x @ (%d, %d)\n", c->window, c->parent, c->x, c->y); } #endif 9wm-1.2.orig/cursor.c100600 1755 1750 13410 6224754221 12773 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include "dat.h" #include "fns.h" typedef struct { int width; int hot[2]; unsigned char mask[64]; unsigned char fore[64]; } Cursordata; Cursordata sweep0data = { 16, {7, 7}, {0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03}, {0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xFE, 0x7F, 0xFE, 0x7F, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00} }; Cursordata boxcursdata = { 16, {7, 7}, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x00, 0x00, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0x00, 0x00} }; Cursordata sightdata = { 16, {7, 7}, {0xF8, 0x1F, 0xFC, 0x3F, 0xFE, 0x7F, 0xDF, 0xFB, 0xCF, 0xF3, 0xC7, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xE3, 0xCF, 0xF3, 0xDF, 0x7B, 0xFE, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F,}, {0x00, 0x00, 0xF0, 0x0F, 0x8C, 0x31, 0x84, 0x21, 0x82, 0x41, 0x82, 0x41, 0x82, 0x41, 0xFE, 0x7F, 0xFE, 0x7F, 0x82, 0x41, 0x82, 0x41, 0x82, 0x41, 0x84, 0x21, 0x8C, 0x31, 0xF0, 0x0F, 0x00, 0x00,} }; Cursordata arrowdata = { 16, {1, 1}, {0xFF, 0x07, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0x07, 0xE7, 0x0F, 0xC7, 0x1F, 0x83, 0x3F, 0x00, 0x7F, 0x00, 0xFE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10,}, {0x00, 0x00, 0xFE, 0x03, 0xFE, 0x00, 0x3E, 0x00, 0x7E, 0x00, 0xFE, 0x00, 0xF6, 0x01, 0xE6, 0x03, 0xC2, 0x07, 0x82, 0x0F, 0x00, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00,} }; Cursordata whitearrow = { 16, {0, 0}, {0xFF, 0x07, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0x07, 0xE7, 0x0F, 0xC7, 0x1F, 0x83, 0x3F, 0x00, 0x7F, 0x00, 0xFE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10,}, {0xFF, 0x07, 0xFF, 0x07, 0x83, 0x03, 0xC3, 0x00, 0xC3, 0x00, 0x83, 0x01, 0x1B, 0x03, 0x3F, 0x06, 0x67, 0x0C, 0xC7, 0x18, 0x83, 0x31, 0x00, 0x63, 0x00, 0xC6, 0x00, 0x6C, 0x00, 0x38, 0x00, 0x10,} }; Cursordata blittarget = { 18, {8, 8}, {0xe0, 0x1f, 0x00, 0xf0, 0x3f, 0x00, 0xf8, 0x7f, 0x00, 0xfc, 0xff, 0x00, 0xfe, 0xff, 0x01, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xfe, 0xff, 0x01, 0xfc, 0xff, 0x00, 0xf8, 0x7f, 0x00, 0xf0, 0x3f, 0x00, 0xe0, 0x1f, 0x00}, {0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x3f, 0x00, 0x38, 0x73, 0x00, 0x8c, 0xc7, 0x00, 0xec, 0xdf, 0x00, 0x66, 0x9b, 0x01, 0x36, 0xb3, 0x01, 0xfe, 0xff, 0x01, 0xfe, 0xff, 0x01, 0x36, 0xb3, 0x01, 0x66, 0x9b, 0x01, 0xec, 0xdf, 0x00, 0x8c, 0xc7, 0x00, 0x38, 0x73, 0x00, 0xf0, 0x3f, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00} }; Cursordata blitarrow = { 18, {1, 1}, {0xff, 0x0f, 0x00, 0xff, 0x07, 0x00, 0xff, 0x03, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x01, 0x00, 0xff, 0x03, 0x00, 0xff, 0x07, 0x00, 0xe7, 0x0f, 0x00, 0xc7, 0x1f, 0x00, 0x87, 0x3f, 0x00, 0x03, 0x7f, 0x00, 0x01, 0xfe, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xf8, 0x03, 0x00, 0xf0, 0x01, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x00}, {0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0xfe, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xf6, 0x01, 0x00, 0xe6, 0x03, 0x00, 0xc2, 0x07, 0x00, 0x82, 0x0f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7c, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00} }; Cursordata blitsweep = { 18, {8, 8}, {0xc4, 0xff, 0x03, 0xce, 0xff, 0x03, 0xdf, 0xff, 0x03, 0x3e, 0x80, 0x03, 0x7c, 0x83, 0x03, 0xf8, 0x83, 0x03, 0xf7, 0x83, 0x03, 0xe7, 0x83, 0x03, 0xf7, 0x83, 0x03, 0xf7, 0x83, 0x03, 0x07, 0x80, 0x03, 0x07, 0x80, 0x03, 0x07, 0x80, 0x03, 0x07, 0x80, 0x03, 0x07, 0x80, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03}, {0x00, 0x00, 0x00, 0x84, 0xff, 0x01, 0x0e, 0x00, 0x01, 0x1c, 0x00, 0x01, 0x38, 0x00, 0x01, 0x70, 0x01, 0x01, 0xe0, 0x01, 0x01, 0xc2, 0x01, 0x01, 0xe2, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00} }; /* * Grey tile pattern for root background */ #define grey_width 4 #define grey_height 2 static char grey_bits[] = { 0x01, 0x04, }; static XColor bl, wh; Cursor getcursor(c, s) Cursordata *c; ScreenInfo *s; { Pixmap f, m; f = XCreatePixmapFromBitmapData(dpy, s->root, (char *)c->fore, c->width, c->width, 1, 0, 1); m = XCreatePixmapFromBitmapData(dpy, s->root, (char *)c->mask, c->width, c->width, 1, 0, 1); return XCreatePixmapCursor(dpy, f, m, &bl, &wh, c->hot[0], c->hot[1]); } void initcurs(s) ScreenInfo *s; { XColor dummy; XAllocNamedColor(dpy, DefaultColormap(dpy, s->num), "black", &bl, &dummy); XAllocNamedColor(dpy, DefaultColormap(dpy, s->num), "white", &wh, &dummy); if (nostalgia) { s->arrow = getcursor(&blitarrow, s); s->target = getcursor(&blittarget, s); s->sweep0 = getcursor(&blitsweep, s); s->boxcurs = getcursor(&blitsweep, s); } else { s->arrow = getcursor(&arrowdata, s); s->target = getcursor(&sightdata, s); s->sweep0 = getcursor(&sweep0data, s); s->boxcurs = getcursor(&boxcursdata, s); } s->root_pixmap = XCreatePixmapFromBitmapData(dpy, s->root, grey_bits, grey_width, grey_height, s->black, s->white, DefaultDepth(dpy, s->num)); } 9wm-1.2.orig/error.c100600 1755 1750 4037 6224754221 12574 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include "dat.h" #include "fns.h" int ignore_badwindow; void fatal(s) char *s; { fprintf(stderr, "9wm: "); perror(s); fprintf(stderr, "\n"); exit(1); } int handler(d, e) Display *d; XErrorEvent *e; { char msg[80], req[80], number[80]; if (initting && (e->request_code == X_ChangeWindowAttributes) && (e->error_code == BadAccess)) { fprintf(stderr, "9wm: it looks like there's already a window manager running; 9wm not started\n"); exit(1); } if (ignore_badwindow && (e->error_code == BadWindow || e->error_code == BadColor)) return 0; XGetErrorText(d, e->error_code, msg, sizeof(msg)); sprintf(number, "%d", e->request_code); XGetErrorDatabaseText(d, "XRequest", number, "", req, sizeof(req)); if (req[0] == '\0') sprintf(req, "", e->request_code); fprintf(stderr, "9wm: %s(0x%x): %s\n", req, e->resourceid, msg); if (initting) { fprintf(stderr, "9wm: failure during initialisation; aborting\n"); exit(1); } return 0; } void graberror(f, err) char *f; int err; { #ifdef DEBUG /* sick of "bug" reports; grab errors "just happen" */ char *s; switch (err) { case GrabNotViewable: s = "not viewable"; break; case AlreadyGrabbed: s = "already grabbed"; break; case GrabFrozen: s = "grab frozen"; break; case GrabInvalidTime: s = "invalid time"; break; case GrabSuccess: return; default: fprintf(stderr, "9wm: %s: grab error: %d\n", f, err); return; } fprintf(stderr, "9wm: %s: grab error: %s\n", f, s); #endif } #ifdef DEBUG_EV #include "showevent/ShowEvent.c" #endif #ifdef DEBUG void dotrace(s, c, e) char *s; Client *c; XEvent *e; { fprintf(stderr, "9wm: %s: c=0x%x", s, c); if (c) fprintf(stderr, " x %d y %d dx %d dy %d w 0x%x parent 0x%x", c->x, c->y, c->dx, c->dy, c->window, c->parent); #ifdef DEBUG_EV if (e) { fprintf(stderr, "\n\t"); ShowEvent(e); } #endif fprintf(stderr, "\n"); } #endif 9wm-1.2.orig/event.c100600 1755 1750 21665 6224754220 12611 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" #include "patchlevel.h" void mainloop(shape_event) int shape_event; { XEvent ev; for (;;) { getevent(&ev); #ifdef DEBUG_EV if (debug) { ShowEvent(&ev); printf("\n"); } #endif switch (ev.type) { default: #ifdef SHAPE if (shape && ev.type == shape_event) shapenotify((XShapeEvent *)&ev); else #endif fprintf(stderr, "9wm: unknown ev.type %d\n", ev.type); break; case ButtonPress: button(&ev.xbutton); break; case ButtonRelease: break; case MapRequest: mapreq(&ev.xmaprequest); break; case ConfigureRequest: configurereq(&ev.xconfigurerequest); break; case CirculateRequest: circulatereq(&ev.xcirculaterequest); break; case UnmapNotify: unmap(&ev.xunmap); break; case CreateNotify: newwindow(&ev.xcreatewindow); break; case DestroyNotify: destroy(ev.xdestroywindow.window); break; case ClientMessage: clientmesg(&ev.xclient); break; case ColormapNotify: cmap(&ev.xcolormap); break; case PropertyNotify: property(&ev.xproperty); break; case SelectionClear: fprintf(stderr, "9wm: SelectionClear (this should not happen)\n"); break; case SelectionNotify: fprintf(stderr, "9wm: SelectionNotify (this should not happen)\n"); break; case SelectionRequest: fprintf(stderr, "9wm: SelectionRequest (this should not happen)\n"); break; case EnterNotify: enter(&ev.xcrossing); break; case ReparentNotify: reparent(&ev.xreparent); break; case FocusIn: focusin(&ev.xfocus); break; case MotionNotify: case Expose: case FocusOut: case ConfigureNotify: case MapNotify: case MappingNotify: /* not interested */ trace("ignore", 0, &ev); break; } } } void configurereq(e) XConfigureRequestEvent *e; { XWindowChanges wc; Client *c; /* we don't set curtime as nothing here uses it */ c = getclient(e->window, 0); trace("configurereq", c, e); e->value_mask &= ~CWSibling; if (c) { gravitate(c, 1); if (e->value_mask & CWX) c->x = e->x; if (e->value_mask & CWY) c->y = e->y; if (e->value_mask & CWWidth) c->dx = e->width; if (e->value_mask & CWHeight) c->dy = e->height; if (e->value_mask & CWBorderWidth) c->border = e->border_width; gravitate(c, 0); if (e->value_mask & CWStackMode) { if (wc.stack_mode == Above) top(c); else e->value_mask &= ~CWStackMode; } if (c->parent != c->screen->root && c->window == e->window) { wc.x = c->x-BORDER; wc.y = c->y-BORDER; wc.width = c->dx+2*(BORDER-1); wc.height = c->dy+2*(BORDER-1); wc.border_width = 1; wc.sibling = None; wc.stack_mode = e->detail; XConfigureWindow(dpy, c->parent, e->value_mask, &wc); sendconfig(c); } } if (c && c->init) { wc.x = BORDER-1; wc.y = BORDER-1; } else { wc.x = e->x; wc.y = e->y; } wc.width = e->width; wc.height = e->height; wc.border_width = 0; wc.sibling = None; wc.stack_mode = Above; e->value_mask &= ~CWStackMode; e->value_mask |= CWBorderWidth; XConfigureWindow(dpy, e->window, e->value_mask, &wc); } void mapreq(e) XMapRequestEvent *e; { Client *c; int i; curtime = CurrentTime; c = getclient(e->window, 0); trace("mapreq", c, e); if (c == 0 || c->window != e->window) { /* workaround for stupid NCDware */ fprintf(stderr, "9wm: bad mapreq c %x w %x, rescanning\n", c, e->window); for (i = 0; i < num_screens; i++) scanwins(&screens[i]); c = getclient(e->window, 0); if (c == 0 || c->window != e->window) { fprintf(stderr, "9wm: window not found after rescan\n"); return; } } switch (c->state) { case WithdrawnState: if (c->parent == c->screen->root) { if (!manage(c, 0)) return; break; } XReparentWindow(dpy, c->window, c->parent, BORDER-1, BORDER-1); XAddToSaveSet(dpy, c->window); /* fall through... */ case NormalState: XMapWindow(dpy, c->window); XMapRaised(dpy, c->parent); top(c); setstate(c, NormalState); if (c->trans != None && current && c->trans == current->window) active(c); break; case IconicState: unhidec(c, 1); break; } } void unmap(e) XUnmapEvent *e; { Client *c; curtime = CurrentTime; c = getclient(e->window, 0); if (c) { switch (c->state) { case IconicState: if (e->send_event) { unhidec(c, 0); withdraw(c); } break; case NormalState: if (c == current) nofocus(); if (!c->reparenting) withdraw(c); break; } c->reparenting = 0; } } void circulatereq(e) XCirculateRequestEvent *e; { fprintf(stderr, "It must be the warlock Krill!\n"); /* :-) */ } void newwindow(e) XCreateWindowEvent *e; { Client *c; ScreenInfo *s; /* we don't set curtime as nothing here uses it */ if (e->override_redirect) return; c = getclient(e->window, 1); if (c && c->window == e->window && (s = getscreen(e->parent))) { c->x = e->x; c->y = e->y; c->dx = e->width; c->dy = e->height; c->border = e->border_width; c->screen = s; if (c->parent == None) c->parent = c->screen->root; } } void destroy(w) Window w; { Client *c; curtime = CurrentTime; c = getclient(w, 0); if (c == 0) return; rmclient(c); /* flush any errors generated by the window's sudden demise */ ignore_badwindow = 1; XSync(dpy, False); ignore_badwindow = 0; } void clientmesg(e) XClientMessageEvent *e; { Client *c; curtime = CurrentTime; if (e->message_type == exit_9wm) { cleanup(); exit(0); } if (e->message_type == restart_9wm) { fprintf(stderr, "*** 9wm restarting ***\n"); cleanup(); execvp(myargv[0], myargv); perror("9wm: exec failed"); exit(1); } if (e->message_type == wm_change_state) { c = getclient(e->window, 0); if (e->format == 32 && e->data.l[0] == IconicState && c != 0) { if (normal(c)) hide(c); } else fprintf(stderr, "9wm: WM_CHANGE_STATE: format %d data %d w 0x%x\n", e->format, e->data.l[0], e->window); return; } fprintf(stderr, "9wm: strange ClientMessage, type 0x%x window 0x%x\n", e->message_type, e->window); } void cmap(e) XColormapEvent *e; { Client *c; int i; /* we don't set curtime as nothing here uses it */ if (e->new) { c = getclient(e->window, 0); if (c) { c->cmap = e->colormap; if (c == current) cmapfocus(c); } else for (c = clients; c; c = c->next) { for (i = 0; i < c->ncmapwins; i++) if (c->cmapwins[i] == e->window) { c->wmcmaps[i] = e->colormap; if (c == current) cmapfocus(c); return; } } } } void property(e) XPropertyEvent *e; { Atom a; int delete; Client *c; /* we don't set curtime as nothing here uses it */ a = e->atom; delete = (e->state == PropertyDelete); c = getclient(e->window, 0); if (c == 0) return; switch (a) { case XA_WM_ICON_NAME: if (c->iconname != 0) XFree((char*) c->iconname); c->iconname = delete ? 0 : getprop(c->window, a); setlabel(c); renamec(c, c->label); return; case XA_WM_NAME: if (c->name != 0) XFree((char*) c->name); c->name = delete ? 0 : getprop(c->window, a); setlabel(c); renamec(c, c->label); return; case XA_WM_TRANSIENT_FOR: gettrans(c); return; } if (a == _9wm_hold_mode) { c->hold = getiprop(c->window, _9wm_hold_mode); if (c == current) draw_border(c, 1); } else if (a == wm_colormaps) { getcmaps(c); if (c == current) cmapfocus(c); } } void reparent(e) XReparentEvent *e; { Client *c; XWindowAttributes attr; ScreenInfo *s; /* we don't set curtime as nothing here uses it */ if (!getscreen(e->event) || e->override_redirect) return; if ((s = getscreen(e->parent)) != 0) { c = getclient(e->window, 1); if (c != 0 && (c->dx == 0 || c->dy == 0)) { XGetWindowAttributes(dpy, c->window, &attr); c->x = attr.x; c->y = attr.y; c->dx = attr.width; c->dy = attr.height; c->border = attr.border_width; c->screen = s; if (c->parent == None) c->parent = c->screen->root; } } else { c = getclient(e->window, 0); if (c != 0 && (c->parent == c->screen->root || withdrawn(c))) rmclient(c); } } #ifdef SHAPE void shapenotify(e) XShapeEvent *e; { Client *c; /* we don't set curtime as nothing here uses it */ c = getclient(e->window, 0); if (c == 0) return; setshape(c); } #endif void enter(e) XCrossingEvent *e; { Client *c; curtime = e->time; if (e->mode != NotifyGrab || e->detail != NotifyNonlinearVirtual) return; c = getclient(e->window, 0); if (c != 0 && c != current) { /* someone grabbed the pointer; make them current */ XMapRaised(dpy, c->parent); top(c); active(c); } } void focusin(e) XFocusChangeEvent *e; { Client *c; curtime = CurrentTime; if (e->detail != NotifyNonlinearVirtual) return; c = getclient(e->window, 0); if (c != 0 && c->window == e->window && c != current) { /* someone grabbed keyboard or seized focus; make them current */ XMapRaised(dpy, c->parent); top(c); active(c); } } 9wm-1.2.orig/grab.c100600 1755 1750 20775 6224754220 12404 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include "dat.h" #include "fns.h" int nobuttons(e) /* Einstuerzende */ XButtonEvent *e; { int state; state = (e->state & AllButtonMask); return (e->type == ButtonRelease) && (state & (state - 1)) == 0; } int grab(w, constrain, mask, curs, t) Window w; Window constrain; int mask; Cursor curs; int t; { int status; if (t == 0) t = timestamp(); status = XGrabPointer(dpy, w, False, mask, GrabModeAsync, GrabModeAsync, constrain, curs, t); return status; } void ungrab(e) XButtonEvent *e; { XEvent ev; if (!nobuttons(e)) for (;;) { XMaskEvent(dpy, ButtonMask | ButtonMotionMask, &ev); if (ev.type == MotionNotify) continue; e = &ev.xbutton; if (nobuttons(e)) break; } XUngrabPointer(dpy, e->time); curtime = e->time; } int menuhit(e, m) XButtonEvent *e; Menu *m; { XEvent ev; int i, n, cur, old, wide, high, status, drawn, warp; int x, y, dx, dy, xmax, ymax; int tx, ty; ScreenInfo *s; if (font == 0) return -1; s = getscreen(e->root); if (s == 0 || e->window == s->menuwin) /* ugly event mangling */ return -1; dx = 0; for (n = 0; m->item[n]; n++) { wide = XTextWidth(font, m->item[n], strlen(m->item[n])) + 4; if (wide > dx) dx = wide; } wide = dx; cur = m->lasthit; if (cur >= n) cur = n - 1; high = font->ascent + font->descent + 1; dy = n*high; x = e->x - wide/2; y = e->y - cur*high - high/2; warp = 0; xmax = DisplayWidth(dpy, s->num); ymax = DisplayHeight(dpy, s->num); if (x < 0) { e->x -= x; x = 0; warp++; } if (x+wide >= xmax) { e->x -= x+wide-xmax; x = xmax-wide; warp++; } if (y < 0) { e->y -= y; y = 0; warp++; } if (y+dy >= ymax) { e->y -= y+dy-ymax; y = ymax-dy; warp++; } if (warp) setmouse(e->x, e->y, s); XMoveResizeWindow(dpy, s->menuwin, x, y, dx, dy); XSelectInput(dpy, s->menuwin, MenuMask); XMapRaised(dpy, s->menuwin); status = grab(s->menuwin, None, MenuGrabMask, None, e->time); if (status != GrabSuccess) { /* graberror("menuhit", status); */ XUnmapWindow(dpy, s->menuwin); return -1; } drawn = 0; for (;;) { XMaskEvent(dpy, MenuMask, &ev); switch (ev.type) { default: fprintf(stderr, "9wm: menuhit: unknown ev.type %d\n", ev.type); break; case ButtonPress: break; case ButtonRelease: if (ev.xbutton.button != e->button) break; x = ev.xbutton.x; y = ev.xbutton.y; i = y/high; if (cur >= 0 && y >= cur*high-3 && y < (cur+1)*high+3) i = cur; if (x < 0 || x > wide || y < -3) i = -1; else if (i < 0 || i >= n) i = -1; else m->lasthit = i; if (!nobuttons(&ev.xbutton)) i = -1; ungrab(&ev.xbutton); XUnmapWindow(dpy, s->menuwin); return i; case MotionNotify: if (!drawn) break; x = ev.xbutton.x; y = ev.xbutton.y; old = cur; cur = y/high; if (old >= 0 && y >= old*high-3 && y < (old+1)*high+3) cur = old; if (x < 0 || x > wide || y < -3) cur = -1; else if (cur < 0 || cur >= n) cur = -1; if (cur == old) break; if (old >= 0 && old < n) XFillRectangle(dpy, s->menuwin, s->gc, 0, old*high, wide, high); if (cur >= 0 && cur < n) XFillRectangle(dpy, s->menuwin, s->gc, 0, cur*high, wide, high); break; case Expose: XClearWindow(dpy, s->menuwin); for (i = 0; i < n; i++) { tx = (wide - XTextWidth(font, m->item[i], strlen(m->item[i])))/2; ty = i*high + font->ascent + 1; XDrawString(dpy, s->menuwin, s->gc, tx, ty, m->item[i], strlen(m->item[i])); } if (cur >= 0 && cur < n) XFillRectangle(dpy, s->menuwin, s->gc, 0, cur*high, wide, high); drawn = 1; } } } Client * selectwin(release, shift, s) int release; int *shift; ScreenInfo *s; { XEvent ev; XButtonEvent *e; int status; Window w; Client *c; status = grab(s->root, s->root, ButtonMask, s->target, 0); if (status != GrabSuccess) { graberror("selectwin", status); /* */ return 0; } w = None; for (;;) { XMaskEvent(dpy, ButtonMask, &ev); e = &ev.xbutton; switch (ev.type) { case ButtonPress: if (e->button != Button3) { ungrab(e); return 0; } w = e->subwindow; if (!release) { c = getclient(w, 0); if (c == 0) ungrab(e); if (shift != 0) *shift = (e->state&ShiftMask) != 0; return c; } break; case ButtonRelease: ungrab(e); if (e->button != Button3 || e->subwindow != w) return 0; if (shift != 0) *shift = (e->state&ShiftMask) != 0; return getclient(w, 0); } } } void sweepcalc(c, x, y) Client *c; int x; int y; { int dx, dy, sx, sy; dx = x - c->x; dy = y - c->y; sx = sy = 1; if (dx < 0) { dx = -dx; sx = -1; } if (dy < 0) { dy = -dy; sy = -1; } dx -= 2*BORDER; dy -= 2*BORDER; if (!c->is9term) { if (dx < c->min_dx) dx = c->min_dx; if (dy < c->min_dy) dy = c->min_dy; } if (c->size.flags & PResizeInc) { dx = c->min_dx + (dx-c->min_dx)/c->size.width_inc*c->size.width_inc; dy = c->min_dy + (dy-c->min_dy)/c->size.height_inc*c->size.height_inc; } if (c->size.flags & PMaxSize) { if (dx > c->size.max_width) dx = c->size.max_width; if (dy > c->size.max_height) dy = c->size.max_height; } c->dx = sx*(dx + 2*BORDER); c->dy = sy*(dy + 2*BORDER); } void dragcalc(c, x, y) Client *c; int x; int y; { c->x = x; c->y = y; } void drawbound(c) Client *c; { int x, y, dx, dy; ScreenInfo *s; s = c->screen; x = c->x; y = c->y; dx = c->dx; dy = c->dy; if (dx < 0) { x += dx; dx = -dx; } if (dy < 0) { y += dy; dy = -dy; } if (dx <= 2 || dy <= 2) return; XDrawRectangle(dpy, s->root, s->gc, x, y, dx-1, dy-1); XDrawRectangle(dpy, s->root, s->gc, x+1, y+1, dx-3, dy-3); } void misleep(msec) int msec; { struct timeval t; t.tv_sec = msec/1000; t.tv_usec = (msec%1000)*1000; select(0, 0, 0, 0, &t); } int sweepdrag(c, e0, recalc) Client *c; XButtonEvent *e0; void (*recalc)(); { XEvent ev; int idle; int cx, cy, rx, ry; int ox, oy, odx, ody; XButtonEvent *e; ox = c->x; oy = c->y; odx = c->dx; ody = c->dy; c->x -= BORDER; c->y -= BORDER; c->dx += 2*BORDER; c->dy += 2*BORDER; if (e0) { c->x = cx = e0->x; c->y = cy = e0->y; recalc(c, e0->x, e0->y); } else getmouse(&cx, &cy, c->screen); XGrabServer(dpy); drawbound(c); idle = 0; for (;;) { if (XCheckMaskEvent(dpy, ButtonMask, &ev) == 0) { getmouse(&rx, &ry, c->screen); if (rx != cx || ry != cy || ++idle > 300) { drawbound(c); if (rx == cx && ry == cy) { XUngrabServer(dpy); XFlush(dpy); misleep(500); XGrabServer(dpy); idle = 0; } recalc(c, rx, ry); cx = rx; cy = ry; drawbound(c); XFlush(dpy); } misleep(50); continue; } e = &ev.xbutton; switch (ev.type) { case ButtonPress: case ButtonRelease: drawbound(c); ungrab(e); XUngrabServer(dpy); if (e->button != Button3 && c->init) goto bad; recalc(c, ev.xbutton.x, ev.xbutton.y); if (c->dx < 0) { c->x += c->dx; c->dx = -c->dx; } if (c->dy < 0) { c->y += c->dy; c->dy = -c->dy; } c->x += BORDER; c->y += BORDER; c->dx -= 2*BORDER; c->dy -= 2*BORDER; if (c->dx < 4 || c->dy < 4 || c->dx < c->min_dx || c->dy < c->min_dy) goto bad; return 1; } } bad: c->x = ox; c->y = oy; c->dx = odx; c->dy = ody; return 0; } int sweep(c) Client *c; { XEvent ev; int status; XButtonEvent *e; ScreenInfo *s; s = c->screen; status = grab(s->root, s->root, ButtonMask, s->sweep0, 0); if (status != GrabSuccess) { graberror("sweep", status); /* */ return 0; } XMaskEvent(dpy, ButtonMask, &ev); e = &ev.xbutton; if (e->button != Button3) { ungrab(e); return 0; } if (c->size.flags & (PMinSize|PBaseSize)) setmouse(e->x+c->min_dx, e->y+c->min_dy, s); XChangeActivePointerGrab(dpy, ButtonMask, s->boxcurs, e->time); return sweepdrag(c, e, sweepcalc); } int drag(c) Client *c; { int status; ScreenInfo *s; s = c->screen; if (c->init) setmouse(c->x-BORDER, c->y-BORDER, s); else { getmouse(&c->x, &c->y, s); /* start at current mouse pos */ c->x += BORDER; c->y += BORDER; } status = grab(s->root, s->root, ButtonMask, s->boxcurs, 0); if (status != GrabSuccess) { graberror("drag", status); /* */ return 0; } return sweepdrag(c, 0, dragcalc); } void getmouse(x, y, s) int *x; int *y; ScreenInfo *s; { Window dw1, dw2; int t1, t2; unsigned int t3; XQueryPointer(dpy, s->root, &dw1, &dw2, x, y, &t1, &t2, &t3); } void setmouse(x, y, s) int x; int y; ScreenInfo *s; { XWarpPointer(dpy, None, s->root, None, None, None, None, x, y); } 9wm-1.2.orig/main.c100600 1755 1750 20614 6224754220 12405 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" #include "patchlevel.h" char *version[] = { "9wm version 1.2, Copyright (c) 1994-1996 David Hogan", 0, }; Display *dpy; ScreenInfo *screens; int initting; XFontStruct *font; int nostalgia; char **myargv; char *termprog; char *shell; Bool shape; int _border = 4; int _inset = 1; int curtime; int debug; int signalled; int num_screens; Atom exit_9wm; Atom restart_9wm; Atom wm_state; Atom wm_change_state; Atom wm_protocols; Atom wm_delete; Atom wm_take_focus; Atom wm_colormaps; Atom _9wm_running; Atom _9wm_hold_mode; char *fontlist[] = { "lucm.latin1.9", "blit", "9x15bold", "lucidasanstypewriter-12", "fixed", "*", 0, }; void usage() { fprintf(stderr, "usage: 9wm [-grey] [-version] [-font fname] [-term prog] [exit|restart]\n"); exit(1); } int main(argc, argv) int argc; char *argv[]; { int i, background, do_exit, do_restart; char *fname; int shape_event, dummy; myargv = argv; /* for restart */ background = do_exit = do_restart = 0; font = 0; fname = 0; for (i = 1; i < argc; i++) if (strcmp(argv[i], "-nostalgia") == 0) nostalgia++; else if (strcmp(argv[i], "-grey") == 0) background = 1; else if (strcmp(argv[i], "-debug") == 0) debug++; else if (strcmp(argv[i], "-font") == 0 && i+1 0) fprintf(stderr, "; patch level %d", PATCHLEVEL); fprintf(stderr, "\n"); exit(0); } else if (argv[i][0] == '-') usage(); else break; for (; i < argc; i++) if (strcmp(argv[i], "exit") == 0) do_exit++; else if (strcmp(argv[i], "restart") == 0) do_restart++; else usage(); if (do_exit && do_restart) usage(); shell = (char *)getenv("SHELL"); if (shell == NULL) shell = DEFSHELL; dpy = XOpenDisplay(""); if (dpy == 0) fatal("can't open display"); initting = 1; XSetErrorHandler(handler); if (signal(SIGTERM, sighandler) == SIG_IGN) signal(SIGTERM, SIG_IGN); if (signal(SIGINT, sighandler) == SIG_IGN) signal(SIGINT, SIG_IGN); if (signal(SIGHUP, sighandler) == SIG_IGN) signal(SIGHUP, SIG_IGN); exit_9wm = XInternAtom(dpy, "9WM_EXIT", False); restart_9wm = XInternAtom(dpy, "9WM_RESTART", False); curtime = -1; /* don't care */ if (do_exit) { sendcmessage(DefaultRootWindow(dpy), exit_9wm, 0L, 1); XSync(dpy, False); exit(0); } if (do_restart) { sendcmessage(DefaultRootWindow(dpy), restart_9wm, 0L, 1); XSync(dpy, False); exit(0); } wm_state = XInternAtom(dpy, "WM_STATE", False); wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False); wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False); wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False); wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False); wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False); _9wm_running = XInternAtom(dpy, "_9WM_RUNNING", False); _9wm_hold_mode = XInternAtom(dpy, "_9WM_HOLD_MODE", False); if (fname != 0) if ((font = XLoadQueryFont(dpy, fname)) == 0) fprintf(stderr, "9wm: warning: can't load font %s\n", fname); if (font == 0) { i = 0; for (;;) { fname = fontlist[i++]; if (fname == 0) { fprintf(stderr, "9wm: warning: can't find a font\n"); break; } font = XLoadQueryFont(dpy, fname); if (font != 0) break; } } if (nostalgia) { _border--; _inset--; } #ifdef SHAPE shape = XShapeQueryExtension(dpy, &shape_event, &dummy); #endif num_screens = ScreenCount(dpy); screens = (ScreenInfo *)malloc(sizeof(ScreenInfo) * num_screens); for (i = 0; i < num_screens; i++) initscreen(&screens[i], i, background); /* set selection so that 9term knows we're running */ curtime = CurrentTime; XSetSelectionOwner(dpy, _9wm_running, screens[0].menuwin, timestamp()); XSync(dpy, False); initting = 0; nofocus(); for (i = 0; i < num_screens; i++) scanwins(&screens[i]); mainloop(shape_event); } void initscreen(s, i, background) ScreenInfo *s; int i; int background; { char *ds, *colon, *dot1; unsigned long mask; XGCValues gv; XSetWindowAttributes attr; s->num = i; s->root = RootWindow(dpy, i); s->def_cmap = DefaultColormap(dpy, i); s->min_cmaps = MinCmapsOfScreen(ScreenOfDisplay(dpy, i)); ds = DisplayString(dpy); colon = rindex(ds, ':'); if (colon && num_screens > 1) { strcpy(s->display, "DISPLAY="); strcat(s->display, ds); colon = s->display + 8 + (colon - ds); /* use version in buf */ dot1 = index(colon, '.'); /* first period after colon */ if (!dot1) dot1 = colon + strlen(colon); /* if not there, append */ sprintf(dot1, ".%d", i); } else s->display[0] = '\0'; s->black = BlackPixel(dpy, i); s->white = WhitePixel(dpy, i); gv.foreground = s->black^s->white; gv.background = s->white; gv.function = GXxor; gv.line_width = 0; gv.subwindow_mode = IncludeInferiors; mask = GCForeground | GCBackground | GCFunction | GCLineWidth | GCSubwindowMode; if (font != 0) { gv.font = font->fid; mask |= GCFont; } s->gc = XCreateGC(dpy, s->root, mask, &gv); initcurs(s); attr.cursor = s->arrow; attr.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | ColormapChangeMask | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask; mask = CWCursor|CWEventMask; XChangeWindowAttributes(dpy, s->root, mask, &attr); XSync(dpy, False); if (background) { XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap); XClearWindow(dpy, s->root); } s->menuwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 1, s->black, s->white); } ScreenInfo * getscreen(w) Window w; { int i; for (i = 0; i < num_screens; i++) if (screens[i].root == w) return &screens[i]; return 0; } Time timestamp() { XEvent ev; if (curtime == CurrentTime) { XChangeProperty(dpy, screens[0].root, _9wm_running, _9wm_running, 8, PropModeAppend, (unsigned char *)"", 0); XMaskEvent(dpy, PropertyChangeMask, &ev); curtime = ev.xproperty.time; } return curtime; } void sendcmessage(w, a, x, isroot) Window w; Atom a; long x; int isroot; { XEvent ev; int status; long mask; memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; ev.xclient.window = w; ev.xclient.message_type = a; ev.xclient.format = 32; ev.xclient.data.l[0] = x; ev.xclient.data.l[1] = timestamp(); mask = 0L; if (isroot) mask = SubstructureRedirectMask; /* magic! */ status = XSendEvent(dpy, w, False, mask, &ev); if (status == 0) fprintf(stderr, "9wm: sendcmessage failed\n"); } void sendconfig(c) Client *c; { XConfigureEvent ce; ce.type = ConfigureNotify; ce.event = c->window; ce.window = c->window; ce.x = c->x; ce.y = c->y; ce.width = c->dx; ce.height = c->dy; ce.border_width = c->border; ce.above = None; ce.override_redirect = 0; XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent*)&ce); } void sighandler() { signalled = 1; } void getevent(e) XEvent *e; { int fd; fd_set rfds; struct timeval t; if (!signalled) { if (QLength(dpy) > 0) { XNextEvent(dpy, e); return; } fd = ConnectionNumber(dpy); FD_ZERO(&rfds); FD_SET(fd, &rfds); t.tv_sec = t.tv_usec = 0; if (select(fd+1, &rfds, NULL, NULL, &t) == 1) { XNextEvent(dpy, e); return; } XFlush(dpy); FD_SET(fd, &rfds); if (select(fd+1, &rfds, NULL, NULL, NULL) == 1) { XNextEvent(dpy, e); return; } if (errno != EINTR || !signalled) { perror("9wm: select failed"); exit(1); } } fprintf(stderr, "9wm: exiting on signal\n"); cleanup(); exit(1); } void cleanup() { Client *c, *cc[2], *next; XWindowChanges wc; int i; /* order of un-reparenting determines final stacking order... */ cc[0] = cc[1] = 0; for (c = clients; c; c = next) { next = c->next; i = normal(c); c->next = cc[i]; cc[i] = c; } for (i = 0; i < 2; i++) { for (c = cc[i]; c; c = c->next) { if (!withdrawn(c)) { gravitate(c, 1); XReparentWindow(dpy, c->window, c->screen->root, c->x, c->y); } wc.border_width = c->border; XConfigureWindow(dpy, c->window, CWBorderWidth, &wc); } } XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, timestamp()); for (i = 0; i < num_screens; i++) cmapnofocus(&screens[i]); XCloseDisplay(dpy); } 9wm-1.2.orig/manage.c100600 1755 1750 22425 6224754220 12713 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" int manage(c, mapped) 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 (!(fixsize ? drag(c) : sweep(c)) && c->is9term) { 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-1), c->dy + 2*(BORDER-1), 1, 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-1, BORDER-1); #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); 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(s) 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(c) Client *c; { Window trans; trans = None; if (XGetTransientForHint(dpy, c->window, &trans) != 0) c->trans = trans; else c->trans = None; } void withdraw(c) 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(c, invert) 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(s, cmap) ScreenInfo *s; Colormap cmap; { if (cmap == None) XInstallColormap(dpy, s->def_cmap); else XInstallColormap(dpy, cmap); } void cmapfocus(c) 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(s) ScreenInfo *s; { installcmap(s, None); } void getcmaps(c) 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(c) 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(c) 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-1, BORDER-1, c->window, ShapeBounding, ShapeSet); XFree((void*)rect); } #endif int _getprop(w, a, type, len, p) Window w; Atom a; Atom type; long len; /* in 32-bit multiples... */ 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(w, a) Window w; Atom a; { unsigned char *p; if (_getprop(w, a, XA_STRING, 100L, &p) <= 0) return 0; return (char *)p; } int get1prop(w, a, type) Window w; Atom a; Atom type; { char **p, *x; if (_getprop(w, a, type, 1L, &p) <= 0) return 0; x = *p; XFree((void*) p); return (int)x; } Window getwprop(w, a) Window w; Atom a; { return get1prop(w, a, XA_WINDOW); } int getiprop(w, a) Window w; Atom a; { return get1prop(w, a, XA_INTEGER); } void setstate(c, state) 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(w, state) Window w; int *state; { long *p = 0; if (_getprop(w, wm_state, wm_state, 2L, (char**)&p) <= 0) return 0; *state = (int) *p; XFree((char *) p); return 1; } void getproto(c) 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, (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); } 9wm-1.2.orig/menu.c100600 1755 1750 10644 6224754220 12427 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include "dat.h" #include "fns.h" Client *hiddenc[MAXHIDDEN]; int numhidden; char *b3items[B3FIXED+MAXHIDDEN+1] = { "New", "Reshape", "Move", "Delete", "Hide", 0, }; Menu b3menu = { b3items, }; Menu egg = { version, }; void button(e) XButtonEvent *e; { int n, shift; Client *c; Window dw; ScreenInfo *s; curtime = e->time; s = getscreen(e->root); if (s == 0) return; c = getclient(e->window, 0); if (c) { e->x += c->x - BORDER + 1; e->y += c->y - BORDER + 1; } else if (e->window != e->root) XTranslateCoordinates(dpy, e->window, s->root, e->x, e->y, &e->x, &e->y, &dw); switch (e->button) { case Button1: if (c) { XMapRaised(dpy, c->parent); top(c); active(c); } return; case Button2: if ((e->state&(ShiftMask|ControlMask))==(ShiftMask|ControlMask)) menuhit(e, &egg); return; default: return; case Button3: break; } if (current && current->screen == s) cmapnofocus(s); switch (n = menuhit(e, &b3menu)) { case 0: /* New */ spawn(s); break; case 1: /* Reshape */ reshape(selectwin(1, 0, s)); break; case 2: /* Move */ move(selectwin(0, 0, s)); break; case 3: /* Delete */ shift = 0; c = selectwin(1, &shift, s); delete(c, shift); break; case 4: /* Hide */ hide(selectwin(1, 0, s)); break; default: /* unhide window */ unhide(n - B3FIXED, 1); break; case -1: /* nothing */ break; } if (current && current->screen == s) cmapfocus(current); } void spawn(s) ScreenInfo *s; { /* * ugly dance to avoid leaving zombies. Could use SIGCHLD, * but it's not very portable. */ if (fork() == 0) { if (fork() == 0) { close(ConnectionNumber(dpy)); if (s->display[0] != '\0') putenv(s->display); if (termprog != NULL) { execl(shell, shell, "-c", termprog, 0); fprintf(stderr, "9wm: exec %s", shell); perror(" failed"); } execlp("9term", "9term", "-9wm", 0); execlp("xterm", "xterm", "-ut", 0); perror("9wm: exec 9term/xterm failed"); exit(1); } exit(0); } wait((int *) 0); } void reshape(c) Client *c; { int odx, ody; if (c == 0) return; odx = c->dx; ody = c->dy; if (sweep(c) == 0) return; active(c); top(c); XRaiseWindow(dpy, c->parent); XMoveResizeWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER, c->dx+2*(BORDER-1), c->dy+2*(BORDER-1)); if (c->dx == odx && c->dy == ody) sendconfig(c); else XMoveResizeWindow(dpy, c->window, BORDER-1, BORDER-1, c->dx, c->dy); } void move(c) Client *c; { if (c == 0) return; if (drag(c) == 0) return; active(c); top(c); XRaiseWindow(dpy, c->parent); XMoveWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER); sendconfig(c); } void delete(c, shift) Client *c; int shift; { if (c == 0) return; if ((c->proto & Pdelete) && !shift) sendcmessage(c->window, wm_protocols, wm_delete, 0); else XKillClient(dpy, c->window); /* let event clean up */ } void hide(c) Client *c; { if (c == 0 || numhidden == MAXHIDDEN) return; if (hidden(c)) { fprintf(stderr, "9wm: already hidden: %s\n", c->label); return; } XUnmapWindow(dpy, c->parent); XUnmapWindow(dpy, c->window); setstate(c, IconicState); if (c == current) nofocus(); hiddenc[numhidden] = c; b3items[B3FIXED+numhidden] = c->label; numhidden++; b3items[B3FIXED+numhidden] = 0; } void unhide(n, map) int n; int map; { Client *c; int i; if (n >= numhidden) { fprintf(stderr, "9wm: unhide: n %d numhidden %d\n", n, numhidden); return; } c = hiddenc[n]; if (!hidden(c)) { fprintf(stderr, "9wm: unhide: not hidden: %s(0x%x)\n", c->label, c->window); return; } if (map) { XMapWindow(dpy, c->window); XMapRaised(dpy, c->parent); setstate(c, NormalState); active(c); top(c); } numhidden--; for (i = n; i < numhidden; i ++) { hiddenc[i] = hiddenc[i+1]; b3items[B3FIXED+i] = b3items[B3FIXED+i+1]; } b3items[B3FIXED+numhidden] = 0; } void unhidec(c, map) Client *c; int map; { int i; for (i = 0; i < numhidden; i++) if (c == hiddenc[i]) { unhide(i, map); return; } fprintf(stderr, "9wm: unhidec: not hidden: %s(0x%x)\n", c->label, c->window); } void renamec(c, name) Client *c; char *name; { int i; if (name == 0) name = "???"; c->label = name; if (!hidden(c)) return; for (i = 0; i < numhidden; i++) if (c == hiddenc[i]) { b3items[B3FIXED+i] = name; return; } } 9wm-1.2.orig/9wm.man100600 1755 1750 5557 6224754217 12525 0ustar krsusers.if t .ds 85 8\(12 .if n .ds 85 8-1/2 .TH 9wm 1 .SH NAME 9wm \- \*(85-like Window Manager for X .SH SYNOPSIS .B 9wm [ .B \-grey ] [ .B \-version ] [ .B \-font .I fname ] [ .B \-term .I termprog ] [ .BR exit | restart ] .SH DESCRIPTION .I 9wm is a window manager for X which attempts to emulate the window management policies of Plan 9's .I \*(85 window manager. .PP The .B \-grey option makes the background light grey, as does \*(85. Use this option for maximum authenticity. .B \-font .I fname sets the font in .IR 9wm 's menu to .IR fname , overriding the default. .B \-term .I termprog specifies an alternative program to run when the .I New menu item is selected. .B \-version prints the current version on standard error, then exits. .PP To make .I 9wm exit, you have to run .B "9wm exit" on the command line. There is no ``exit'' menu item. .PP .I 9wm is click-to-type: it has a notion of the current window, which is usually on top, and always has its border darkened. Characters typed at the keyboard go to the current window, and mouse clicks outside the current window are swallowed up by .IR 9wm . To make another window the current one, click on it with button 1. Unlike other X window managers, 9wm implements `mouse focus': mouse events are sent only to the current window. .PP A menu of window operations is available by pressing button 3 outside the current window. The first of these, .IR New , attempts to spawn a .I 9term process (or .I xterm if .I 9term is not available). The new .I 9term will request that its outline be swept using button 3 of the mouse, by changing the cursor. .RI ( xterm defaults to a fixed size, and thus wants to be dragged; pressing button 3 places it.) .PP The next four menu items are .IR Reshape , .IR Move , .IR Delete , and .IR Hide . All of the operations change the cursor into a target, prompting the user to click button 3 on one of the windows to select it for the operation. At this stage, clicking button 1 or 2 will abort the operation. Otherwise, if the operation was .IR Resize , the user is prompted to sweep out the new outline with button 3. If it was .IR Move , the user should keep the button held down after the initial click that selected the window, and drag the window to the right place before releasing. In either case, button 1 or 2 will abort the operation. .PP If the .I Delete operation is selected, the window will be deleted when the button is released. This typically kills the client that owns the window. The .I Hide operation just makes the window invisible. While hidden, the window's name appears on the bottom of the button 3 menu. Selecting that item brings the window back (unhides it). This operation replaces the iconification feature provided by other window managers. .SH BUGS Is not completely compatible with \*(85. .PP There is a currently a compiled-in limit of 32 hidden windows. .SH "SEE ALSO" .IR 9term (1), .IR xterm (1). 9wm-1.2.orig/Imakefile100600 1755 1750 1277 6224754220 13112 0ustar krsusers INCLUDES = -I$(TOP) DEPLIBS = $(DEPXLIB) LOCAL_LIBRARIES = $(XLIB) DEFINES = -DSHAPE # -g3 -DDEBUG -DDEBUG_EV SRCS = main.c event.c manage.c menu.c client.c grab.c cursor.c error.c OBJS = main.o event.o manage.o menu.o client.o grab.o cursor.o error.o HFILES = dat.h fns.h patchlevel.h MFILES = README 9wm.man Imakefile Makefile.no-imake ComplexProgramTarget(9wm) bun: bundle $(MFILES) $(SRCS) $(HFILES) >bun dist: bundle $(MFILES) main.c event.c manage.c >bun1 bundle menu.c client.c grab.c cursor.c error.c $(HFILES) >bun2 trout: 9wm.man troff -man 9wm.man >trout vu: trout xditview trout clean:: $(RM) bun bun[12] trout core 9wm-1.2.orig/dat.h100600 1755 1750 4671 6224754221 12224 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #define BORDER _border #define INSET _inset #define MAXHIDDEN 32 #define B3FIXED 5 #define AllButtonMask (Button1Mask|Button2Mask|Button3Mask \ |Button4Mask|Button5Mask) #define ButtonMask (ButtonPressMask|ButtonReleaseMask) #define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask) #define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask) #ifdef Plan9 #define DEFSHELL "/bin/rc" #else #define DEFSHELL "/bin/sh" #endif typedef struct Client Client; typedef struct Menu Menu; typedef struct ScreenInfo ScreenInfo; struct Client { Window window; Window parent; Window trans; Client *next; Client *revert; int x; int y; int dx; int dy; int border; XSizeHints size; int min_dx; int min_dy; int state; int init; int reparenting; int is9term; int hold; int proto; char *label; char *instance; char *class; char *name; char *iconname; Colormap cmap; int ncmapwins; Window *cmapwins; Colormap *wmcmaps; ScreenInfo *screen; }; #define hidden(c) ((c)->state == IconicState) #define withdrawn(c) ((c)->state == WithdrawnState) #define normal(c) ((c)->state == NormalState) /* c->proto */ #define Pdelete 1 #define Ptakefocus 2 struct Menu { char **item; char *(*gen)(); int lasthit; }; struct ScreenInfo { int num; Window root; Window menuwin; Colormap def_cmap; GC gc; unsigned long black; unsigned long white; int min_cmaps; Cursor target; Cursor sweep0; Cursor boxcurs; Cursor arrow; Pixmap root_pixmap; char display[256]; /* arbitrary limit */ }; /* main.c */ extern Display *dpy; extern ScreenInfo *screens; extern int num_screens; extern int initting; extern XFontStruct *font; extern int nostalgia; extern char **myargv; extern Bool shape; extern char *termprog; extern char *shell; extern char *version[]; extern int _border; extern int _inset; extern int curtime; extern int debug; extern Atom exit_9wm; extern Atom restart_9wm; extern Atom wm_state; extern Atom wm_change_state; extern Atom _9wm_hold_mode; extern Atom wm_protocols; extern Atom wm_delete; extern Atom wm_take_focus; extern Atom wm_colormaps; /* client.c */ extern Client *clients; extern Client *current; /* menu.c */ extern Client *hiddenc[]; extern int numhidden; extern char *b3items[]; extern Menu b3menu; /* error.c */ extern int ignore_badwindow; 9wm-1.2.orig/fns.h100600 1755 1750 2710 6224754221 12232 0ustar krsusers/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #ifdef DEBUG #define trace(s, c, e) dotrace((s), (c), (e)) #else #define trace(s, c, e) #endif /* main.c */ void usage(); void initscreen(); ScreenInfo *getscreen(); Time timestamp(); void sendcmessage(); void sendconfig(); void sighandler(); void getevent(); void cleanup(); /* event.c */ void mainloop(); void configurereq(); void mapreq(); void circulatereq(); void unmap(); void newwindow(); void destroy(); void clientmesg(); void cmap(); void property(); void shapenotify(); void enter(); void focusin(); void reparent(); /* manage.c */ int manage(); void scanwins(); void setshape(); void withdraw(); void gravitate(); void cmapfocus(); void cmapnofocus(); void getcmaps(); int _getprop(); char *getprop(); Window getwprop(); int getiprop(); int getstate(); void setstate(); void setlabel(); void getproto(); void gettrans(); /* menu.c */ void button(); void spawn(); void reshape(); void move(); void delete(); void hide(); void unhide(); void unhidec(); void renamec(); /* client.c */ void setactive(); void draw_border(); void active(); void nofocus(); void top(); Client *getclient(); void rmclient(); void dump_revert(); void dump_clients(); /* grab.c */ int menuhit(); Client *selectwin(); int sweep(); int drag(); void getmouse(); void setmouse(); /* error.c */ int handler(); void fatal(); void graberror(); void showhints(); void dotrace(); /* cursor.c */ void initcurs(); 9wm-1.2.orig/patchlevel.h100600 1755 1750 25 6224754221 13530 0ustar krsusers#define PATCHLEVEL 0 9wm-1.2.orig/Makefile.no-imake100600 1755 1750 1545 6224754220 14436 0ustar krsusers# # This Makefile is provided in case you have no imake, or it # doesn't work on your system. Copy this file to "Makefile" # and edit the variables below to suit your system. Be sure # to define whatever compilation flags your system needs, eg # if you're using AIX, add "-D_BSD -D_BSD_INCLUDES" to "CFLAGS". # CFLAGS = -g -DSHAPE LDFLAGS = -lXext -lX11 BIN = /usr/bin/X11 MANDIR = /usr/man/man1 MANSUFFIX = 1 # # These variables shouldn't need to be changed # OBJS = main.o event.o manage.o menu.o client.o grab.o cursor.o error.o HFILES = dat.h fns.h # # Or these rules either # all: 9wm 9wm: $(OBJS) $(CC) $(CFLAGS) -o 9wm $(OBJS) $(LDFLAGS) install: 9wm cp 9wm $(BIN)/9wm install.man: cp 9wm.man $(MANDIR)/9wm.$(MANSUFFIX) $(OBJS): $(HFILES) trout: 9wm.man troff -man 9wm.man >trout vu: trout xditview trout clean: rm -f 9wm *.o core bun trout 9wm-1.2.orig/README100600 1755 1750 14666 6224754217 12215 0ustar krsusers 9wm Version 1.2 Copyright 1994-1996 David Hogan. What is 9wm? ============ 9wm is an X window manager which attempts to emulate the Plan 9 window manager 8-1/2 as far as possible within the constraints imposed by X. It provides a simple yet comfortable user interface, without garish decorations or title-bars. Or icons. And it's click-to-type. This will not appeal to everybody, but if you're not put off yet then read on. (And don't knock it until you've tried it.) One major difference between 9wm and 8-1/2 is that the latter provides windows of text with a typescript interface, and doesn't need to run a separate program to emulate a terminal. 9wm, as an X window manager, does require a separate program. For better 8-1/2 emulation, you should obtain Matthew Farrow's "9term" program (ftp://ftp.cs.su.oz.au/matty/unicode), version 1.6 or later (earlier versions don't cooperate with 9wm in implementing "hold mode"). Of course, you can run xterm under 9wm as well. What is 9wm not? ================ 9wm is not a virtual window manager. It is not customisable to any great extent. It is not large and unwieldy, and doesn't use the X toolkit. Requests to make it any of these things will be silently ignored (or flamed if I have had a bad day :-) If you want tvtwm or mwm, you know where to get them... Where do I get it? ================== The latest version of 9wm is held at ftp://ftp.cs.su.oz.au/dhog/9wm Author ====== 9wm was written by David Hogan (dhog@cs.su.oz.au), a postgraduate student at the Basser Department of Computer Science, University of Sydney (http://www.cs.su.oz.au/~dhog/). Licence ======= 9wm is free software, and is Copyright (c) 1994-1996 by David Hogan. Permission is granted to all sentient beings to use this software, to make copies of it, and to distribute those copies, provided that: (1) the copyright and licence notices are left intact (2) the recipients are aware that it is free software (3) any unapproved changes in functionality are either (i) only distributed as patches or (ii) distributed as a new program which is not called 9wm and whose documentation gives credit where it is due (4) the author is not held responsible for any defects or shortcomings in the software, or damages caused by it. There is no warranty for this software. Have a nice day. How do I compile/install it? ============================ Assuming your system is correctly configured, you should only need to run xmkmf to generate the Makefile, and then run make or make install. make install.man should copy the manpage (9wm.man) to the appropriate directory. If the make fails, complaining that the function _XShapeQueryExtension does not exist, try removing the "-DSHAPE" from the Imakefile, and run xmkmf and make again. If you don't have imake, or it is misconfigured, or you would prefer not to use it, try copying the file "Makefile.no-imake" to "Makefile", then edit the definitions in this Makefile to suit your system. This may require defining suitable compilation flags for your system (normally imake does this for you). For instance, on AIX you must include "-DBSD_INCLUDES" in CFLAGS. How do I use it? ================ See the manual page for details. You should probably read the man page for 9term as well. What if I find a bug? ===================== Please mail all bug reports to 9wm-bugs@plan9.cs.su.oz.au, so that I can incorporate fixes into the next release. If you can tell me how to fix it, all the better. Known Problems/Bugs =================== 9wm tries hard to emulate 8-1/2, but isn't 100% compatible. If you are an experienced 8-1/2 user, please be patient with it. One intentional difference between 9wm and 8-1/2 is in the behaviour of the menu when the last hidden item is unhidden. Under 8-1/2, when the menu is next used, it pops up with "New" selected. Under 9wm, the (new) last menu item will be selected. This is a feature. It may be confusing if you frequently switch between 9wm and 8-1/2. If you don't like this feature, email me for the one line fix. There have been some problems encountered when resizing 9term on some platforms. This turns out to be a problem in 9term (actually in libXg, to be precise). Newer versions of 9term should be immune to this, see matty@cs.su.oz.au if your 9term needs fixing. Some client programs do weird things. One of these is Frame Maker. It appears that if it has a modal dialog on the screen, then if any of its windows are current, all keypresses are redirected to the modal dialog. This is not 9wm's fault -- Frame Maker is doing this. Programs like Netscape Navigator like to put riddiculously long icon name properties on their windows, of the form "Netscape: blah blah". There is no way that I know of to stop netscape from doing this. For this reason, 9wm truncates labels at the first colon it finds. This keeps the button 3 menu from becoming excessively wide. Note that with same applications, you can use an iconName resource to set the label; this works well for "xman", whose default icon name of "Manual Browser" is a tad too long. See Also ======== http://www.cs.su.oz.au/~dhog/ The 9wm Home Page ftp://ftp.cs.su.oz.au/matty/unicode/ for source to 9term (get README first) ftp://plan9.att.com/plan9/unixsrc/sam/ for source && info on Rob Pike's editor "sam" ftp://rtfm.mit.edu/pub/usenet/news.answers/unix-faq/shell/rc for information on a publically available implementation of the Plan 9 shell "rc" for unix (or look in comp.unix.shell). ftp://viz.tamu.edu/pub/rc for source to the abovementioned implementation of rc. http://plan9.att.com/plan9/ http://plan9.att.com/magic/man2html/1/8%c2%bd for information on Plan 9 (including the 8-1/2 manual entry) Acknowledgements ================ Thanks to Rob Pike for writing the original 8-1/2 program (and before that, mux) which inspired the writing of 9wm. Thanks to John Mackin, whose gwm "wool code" for emulating mux was also an inspiration: I used it (and hacked it) until I got too frustrated with gwm's large memory requirements and lack of speed (sorry Colas!), and decided to write a dedicated program. Thanks to Matthew Farrow for writing 9term. A big thanks to Dave Edmondson for adding support for multi-screen displays. The following people helped beta test 9wm: John Mackin Noel Hunt Fred Curtis James Matthew Farrow Danny Yee Arnold Robbins Byron Rakitzis micro@cooper.edu