client.c (5575B)
1 /* Copyright (c) 1994-1996 David Hogan, see README for licence details */ 2 #include <stdio.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <X11/X.h> 7 #include <X11/Xlib.h> 8 #include <X11/Xutil.h> 9 #include "dat.h" 10 #include "fns.h" 11 12 Client *clients; 13 Client *current; 14 15 void 16 setactive(Client *c, int on) 17 { 18 /* dbg("setactive client %x %d", c->window, c->on); */ 19 20 if(c->parent == c->screen->root) 21 return; 22 23 if(on){ 24 XUngrabButton(dpy, AnyButton, AnyModifier, c->parent); 25 XSetInputFocus(dpy, c->window, RevertToPointerRoot, timestamp()); 26 if(c->proto & Ptakefocus) 27 sendcmessage(c->window, wm_protocols, wm_take_focus, 0, 1); 28 cmapfocus(c); 29 }else{ 30 if(c->proto & Plosefocus) 31 sendcmessage(c->window, wm_protocols, wm_lose_focus, 0, 1); 32 XGrabButton(dpy, AnyButton, AnyModifier, c->parent, False, 33 ButtonMask, GrabModeAsync, GrabModeSync, None, None); 34 } 35 draw_border(c, on); 36 } 37 38 void 39 draw_border(Client *c, int active) 40 { 41 unsigned long pixel; 42 43 if(active){ 44 if(c->hold) 45 pixel = c->screen->activeholdborder; 46 else 47 pixel = c->screen->activeborder; 48 }else{ 49 if(c->hold) 50 pixel = c->screen->inactiveholdborder; 51 else 52 pixel = c->screen->inactiveborder; 53 } 54 55 if(debug) fprintf(stderr, "draw_border %p pixel %ld active %d hold %d\n", (void*)c, pixel, active, c->hold); 56 XSetWindowBackground(dpy, c->parent, pixel); 57 XClearWindow(dpy, c->parent); 58 } 59 60 void 61 active(Client *c) 62 { 63 Client *cc; 64 65 if(c == 0){ 66 fprintf(stderr, "rio: active(c==0)\n"); 67 return; 68 } 69 if(c == current) 70 return; 71 if(current){ 72 setactive(current, 0); 73 if(current->screen != c->screen) 74 cmapnofocus(current->screen); 75 } 76 setactive(c, 1); 77 for(cc = clients; cc; cc = cc->next) 78 if(cc->revert == c) 79 cc->revert = c->revert; 80 c->revert = current; 81 while(c->revert && !normal(c->revert)) 82 c->revert = c->revert->revert; 83 current = c; 84 #ifdef DEBUG 85 if(debug) 86 dump_revert(); 87 #endif 88 } 89 90 void 91 nofocus(void) 92 { 93 static Window w = 0; 94 int mask; 95 XSetWindowAttributes attr; 96 Client *c; 97 98 if(current){ 99 setactive(current, 0); 100 for(c = current->revert; c; c = c->revert) 101 if(normal(c)){ 102 active(c); 103 return; 104 } 105 cmapnofocus(current->screen); 106 /* if no candidates to revert to, fall through */ 107 } 108 current = 0; 109 if(w == 0){ 110 mask = CWOverrideRedirect/*|CWColormap*/; 111 attr.override_redirect = 1; 112 /* attr.colormap = screens[0].def_cmap;*/ 113 w = XCreateWindow(dpy, screens[0].root, 0, 0, 1, 1, 0, 114 0 /*screens[0].depth*/, InputOnly, screens[0].vis, mask, &attr); 115 XMapWindow(dpy, w); 116 } 117 XSetInputFocus(dpy, w, RevertToPointerRoot, timestamp()); 118 } 119 120 void 121 top(Client *c) 122 { 123 Client **l, *cc; 124 125 l = &clients; 126 for(cc = *l; cc; cc = *l){ 127 if(cc == c){ 128 *l = c->next; 129 c->next = clients; 130 clients = c; 131 return; 132 } 133 l = &cc->next; 134 } 135 fprintf(stderr, "rio: %p not on client list in top()\n", (void*)c); 136 } 137 138 Client * 139 getclient(Window w, int create) 140 { 141 Client *c; 142 143 if(w == 0 || getscreen(w)) 144 return 0; 145 146 for(c = clients; c; c = c->next) 147 if(c->window == w || c->parent == w) 148 return c; 149 150 if(!create) 151 return 0; 152 153 c = (Client *)malloc(sizeof(Client)); 154 if (!c){ 155 fprintf(stderr, "rio: Failed to allocate memory\n"); 156 exit(1); 157 } 158 159 memset(c, 0, sizeof(Client)); 160 c->window = w; 161 /* c->parent will be set by the caller */ 162 c->parent = None; 163 c->reparenting = 0; 164 c->state = WithdrawnState; 165 c->init = 0; 166 c->cmap = None; 167 c->label = c->class = 0; 168 c->revert = 0; 169 c->is9term = 0; 170 c->hold = 0; 171 c->ncmapwins = 0; 172 c->cmapwins = 0; 173 c->wmcmaps = 0; 174 c->next = clients; 175 c->virt = virt; 176 clients = c; 177 return c; 178 } 179 180 void 181 rmclient(Client *c) 182 { 183 Client *cc; 184 185 for(cc = current; cc && cc->revert; cc = cc->revert) 186 if(cc->revert == c) 187 cc->revert = cc->revert->revert; 188 189 if(c == clients) 190 clients = c->next; 191 for(cc = clients; cc && cc->next; cc = cc->next) 192 if(cc->next == c) 193 cc->next = cc->next->next; 194 195 if(hidden(c)) 196 unhidec(c, 0); 197 198 if(c->parent != c->screen->root) 199 XDestroyWindow(dpy, c->parent); 200 201 c->parent = c->window = None; /* paranoia */ 202 if(current == c){ 203 current = c->revert; 204 if(current == 0) 205 nofocus(); 206 else { 207 if(current->screen != c->screen) 208 cmapnofocus(c->screen); 209 setactive(current, 1); 210 } 211 } 212 if(c->ncmapwins != 0){ 213 XFree((char *)c->cmapwins); 214 free((char *)c->wmcmaps); 215 } 216 if(c->iconname != 0) 217 XFree((char*) c->iconname); 218 if(c->name != 0) 219 XFree((char*) c->name); 220 if(c->instance != 0) 221 XFree((char*) c->instance); 222 if(c->class != 0) 223 XFree((char*) c->class); 224 memset(c, 0, sizeof(Client)); /* paranoia */ 225 free(c); 226 } 227 228 #ifdef DEBUG 229 void 230 dump_revert(void) 231 { 232 Client *c; 233 int i; 234 235 i = 0; 236 for(c = current; c; c = c->revert){ 237 fprintf(stderr, "%s(%x:%d)", c->label ? c->label : "?", (int)c->window, c->state); 238 if(i++ > 100) 239 break; 240 if(c->revert) 241 fprintf(stderr, " -> "); 242 } 243 if(current == 0) 244 fprintf(stderr, "empty"); 245 fprintf(stderr, "\n"); 246 } 247 248 void 249 dump_clients(void) 250 { 251 Client *c; 252 253 for(c = clients; c; c = c->next) 254 fprintf(stderr, "w 0x%x parent 0x%x @ (%d, %d)\n", (int)c->window, (int)c->parent, c->x, c->y); 255 } 256 #endif 257 258 void 259 shuffle(int up) 260 { 261 Client **l, *c; 262 263 if(clients == 0 || clients->next == 0) 264 return; 265 if(!up){ 266 c = 0; 267 /*for(c=clients; c->next; c=c->next) */ 268 /* ; */ 269 for(l=&clients; (*l)->next; l=&(*l)->next) 270 if ((*l)->state == 1) 271 c = *l; 272 if (c == 0) 273 return; 274 XMapRaised(dpy, c->parent); 275 top(c); 276 active(c); 277 }else{ 278 c = clients; 279 for(l=&clients; *l; l=&(*l)->next) 280 ; 281 clients = c->next; 282 *l = c; 283 c->next = 0; 284 XLowerWindow(dpy, c->window); 285 } 286 /* XMapRaised(dpy, clients->parent); */ 287 /* top(clients); */ 288 /* active(clients); */ 289 }