|  | /* Copyright (c) 1994-1996 David Hogan, see README for licence details */ | 
|  | #include <stdio.h> | 
|  | #include <unistd.h> | 
|  | #include <stdlib.h> | 
|  | #include <string.h> | 
|  | #include <X11/X.h> | 
|  | #include <X11/Xlib.h> | 
|  | #include <X11/Xutil.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, "rio: 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(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; | 
|  |  | 
|  | 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) | 
|  | if ((*l)->state == 1) | 
|  | c = *l; | 
|  | if (c == 0) | 
|  | return; | 
|  | XMapRaised(dpy, c->parent); | 
|  | top(c); | 
|  | active(c); | 
|  | }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); */ | 
|  | } | 
|  |  |