/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include #include "config.h" #include "dat.h" #include "fns.h" Client* clients; Client* current; void setactive(Client* c, int on) { /* dbg("setactive client %x %d", c->window, c->on); */ if (c->parent == c->screen->root) return; 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, 1); cmapfocus(c); } else { if (c->proto & Plosefocus) sendcmessage(c->window, wm_protocols, wm_lose_focus, 0, 1); XGrabButton( dpy, AnyButton, AnyModifier, c->parent, False, ButtonMask, GrabModeAsync, GrabModeSync, None, None); } draw_border(c, on); } void draw_border(Client* c, int active) { unsigned long pixel; if (active) { if (c->hold) pixel = c->screen->activeholdborder; else pixel = c->screen->activeborder; } else { if (c->hold) pixel = c->screen->inactiveholdborder; else pixel = c->screen->inactiveborder; } if (debug) fprintf( stderr, "draw_border %p pixel %ld active %d hold %d\n", (void*)c, pixel, active, c->hold); XSetWindowBackground(dpy, c->parent, pixel); XClearWindow(dpy, c->parent); } void active(Client* c) { Client* cc; if (c == 0) { fprintf(stderr, "ryudo: active(c==0)\n"); return; } if (c == current) return; #ifdef AUTOSTICK if (isautostick(c)) return; #endif 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(void) { 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 /*|CWColormap*/; attr.override_redirect = 1; /* attr.colormap = screens[0].def_cmap;*/ w = XCreateWindow( dpy, screens[0].root, 0, 0, 1, 1, 0, 0 /*screens[0].depth*/, InputOnly, screens[0].vis, mask, &attr); XMapWindow(dpy, w); } XSetInputFocus(dpy, w, RevertToPointerRoot, timestamp()); } void top(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, "rio: %p not on client list in top()\n", (void*)c); } Client* getclient(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; c->virt = virt; clients = c; return c; } void rmclient(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(void) { Client* c; int i; i = 0; for (c = current; c; c = c->revert) { fprintf( stderr, "%s(%x:%d)", c->label ? c->label : "?", (int)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(void) { Client* c; for (c = clients; c; c = c->next) fprintf( stderr, "w 0x%x parent 0x%x @ (%d, %d)\n", (int)c->window, (int)c->parent, c->x, c->y); } #endif void shuffle(int up) { Client **l, *c; static XWindowAttributes ra; XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &ra); if (clients == 0 || clients->next == 0) return; if (!up) { c = 0; /*for(c=clients; c->next; c=c->next) */ /* ; */ for (l = &clients; (*l)->next; l = &(*l)->next) #ifdef AUTOSTICK if ((*l)->state == 1 && !isautostick(*l)) c = *l; #else if ((*l)->state == 1) c = *l; #endif if (c == 0) return; XMapRaised(dpy, c->parent); top(c); active(c); if (zoom) { quickreshape( c, -BORDER, -BORDER, ra.width + 2 * BORDER, ra.height + 2 * BORDER); } } else { c = clients; for (l = &clients; *l; l = &(*l)->next) ; clients = c->next; *l = c; c->next = 0; XLowerWindow(dpy, c->window); } /* XMapRaised(dpy, clients->parent); */ /* top(clients); */ /* active(clients); */ } #ifdef AUTOSTICK int isautostick(Client* c) { static char* autostick[] = AUTOSTICK; char** a = autostick; while (*a) { if (c && c->class && strstr(c->class, *a)) { return 1; } ++a; } return 0; } #endif #ifdef ALWAYSDRAW int shouldalwaysdraw(Client* c) { static char* alwaysdraw[] = ALWAYSDRAW; char** a = alwaysdraw; while (*a) { if (c && c->class && strstr(c->class, *a)) { return 1; } ++a; } return 0; } #endif int isterminalwindow(Client* c) { static char* termnames[] = TERMINALS; char** t = termnames; while (*t) { if (c && c->class && strstr(c->class, *t)) { return 1; } ++t; } return 0; } #if defined(OPACITY) && defined(TRANSPARENTLIST) int istransparent(Client* c) { static char* transnames[] = TRANSPARENTLIST; char** t = transnames; while (*t) { if (c && c->class && strstr(c->class, *t)) { return 1; } ++t; } return 0; } #endif void ensureactive() { if (!current) shuffle(0); }