Blob


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"
12 Client *clients;
13 Client *current;
15 void
16 setactive(Client *c, int on)
17 {
18 /* dbg("setactive client %x %d", c->window, c->on); */
20 if(c->parent == c->screen->root)
21 return;
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 }
38 void
39 draw_border(Client *c, int active)
40 {
41 unsigned long pixel;
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 }
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 }
60 void
61 active(Client *c)
62 {
63 Client *cc;
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 }
90 void
91 nofocus(void)
92 {
93 static Window w = 0;
94 int mask;
95 XSetWindowAttributes attr;
96 Client *c;
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;
105 cmapnofocus(current->screen);
106 /* if no candidates to revert to, fall through */
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);
117 XSetInputFocus(dpy, w, RevertToPointerRoot, timestamp());
120 void
121 top(Client *c)
123 Client **l, *cc;
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;
133 l = &cc->next;
135 fprintf(stderr, "rio: %p not on client list in top()\n", (void*)c);
138 Client *
139 getclient(Window w, int create)
141 Client *c;
143 if(w == 0 || getscreen(w))
144 return 0;
146 for(c = clients; c; c = c->next)
147 if(c->window == w || c->parent == w)
148 return c;
150 if(!create)
151 return 0;
153 c = (Client *)malloc(sizeof(Client));
154 if (!c){
155 fprintf(stderr, "rio: Failed to allocate memory\n");
156 exit(1);
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;
180 void
181 rmclient(Client *c)
183 Client *cc;
185 for(cc = current; cc && cc->revert; cc = cc->revert)
186 if(cc->revert == c)
187 cc->revert = cc->revert->revert;
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;
195 if(hidden(c))
196 unhidec(c, 0);
198 if(c->parent != c->screen->root)
199 XDestroyWindow(dpy, c->parent);
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);
212 if(c->ncmapwins != 0){
213 XFree((char *)c->cmapwins);
214 free((char *)c->wmcmaps);
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);
228 #ifdef DEBUG
229 void
230 dump_revert(void)
232 Client *c;
233 int i;
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, " -> ");
243 if(current == 0)
244 fprintf(stderr, "empty");
245 fprintf(stderr, "\n");
248 void
249 dump_clients(void)
251 Client *c;
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);
256 #endif
258 void
259 shuffle(int up)
261 Client **l, *c;
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)
281 clients = c->next;
282 *l = c;
283 c->next = 0;
284 XLowerWindow(dpy, c->window);
286 /* XMapRaised(dpy, clients->parent); */
287 /* top(clients); */
288 /* active(clients); */