1 /* Copyright (c) 1994 David Hogan, 2000 Benjamin Drieu see README for licence details */
2 #include <stdio.h>
3 #include <string.h>
4 #include <X11/X.h>
5 #include <X11/Xlib.h>
6 #include <X11/Xutil.h>
7 #include <X11/keysym.h>
8 #include "dat.h"
9 #include "fns.h"
10 
11 Client      *clients;
12 Client      *current = NULL;	/* paranoid */
13 
14 void
setactive(c,on)15 setactive(c, on)
16 Client *c;
17 int on;
18 {
19     if (on) {
20         XUngrabButton(dpy, AnyButton, AnyModifier, c->parent);
21 	XSetInputFocus(dpy, c->window, RevertToPointerRoot, timestamp());
22 
23 	if (use_keys)
24 	  {
25 	    XGrabKey(dpy,
26 		     XKeysymToKeycode(dpy, XK_Tab),
27 		     ControlMask,
28 		     root, False, GrabModeAsync, GrabModeAsync);
29 	    XGrabKey(dpy,
30 		     XKeysymToKeycode(dpy, XK_Tab),
31 		     ControlMask|ShiftMask,
32 		     root, False, GrabModeAsync, GrabModeAsync);
33 	  }
34 
35         if (c->proto & Ptakefocus)
36             sendcmessage(c->window, wm_protocols, wm_take_focus);
37         cmapfocus(c);
38     }
39     else
40         XGrabButton(dpy, AnyButton, AnyModifier, c->parent, False,
41             ButtonMask, GrabModeAsync, GrabModeSync, None, None);
42     draw_border(c, on);
43 }
44 
45 void
draw_border(c,active)46 draw_border(c, active)
47 Client *c;
48 int active;
49 {
50     XSetWindowBackground(dpy, c->parent, active ? black : white);
51     XClearWindow(dpy, c->parent);
52     if (c->hold && active)
53         XDrawRectangle(dpy, c->parent, gc, 1, 1, c->dx+BORDER-1, c->dy+BORDER-1);
54 }
55 
56 #ifdef  DEBUG
57 void
dump_revert()58 dump_revert()
59 {
60     Client *c;
61     int i;
62 
63     i = 0;
64     for (c = current; c; c = c->revert) {
65         fprintf(stderr, "%s(%x:%d)", c->label ? c->label : "?", c->window, c->state);
66         if (i++ > 100)
67             break;
68         if (c->revert)
69             fprintf(stderr, " -> ");
70     }
71     if (current == 0)
72         fprintf(stderr, "empty");
73     fprintf(stderr, "\n");
74 }
75 
76 void
dump_clients()77 dump_clients()
78 {
79     Client *c;
80 
81     for (c = clients; c; c = c->next)
82         fprintf(stderr, "w 0x%x parent 0x%x @ (%d, %d)\n", c->window, c->parent, c->x, c->y);
83 }
84 #endif
85 
86 void
active(c)87 active(c)
88 Client *c;
89 {
90     Client *cc;
91 
92     if (c == 0) {
93         fprintf(stderr, "9wm: active(c==0)\n");
94         return;
95     }
96     if (c == current)
97         return;
98     if (current)
99         setactive(current, 0);
100     setactive(c, 1);
101     for (cc = clients; cc; cc = cc->next)
102         if (cc->revert == c)
103             cc->revert = c->revert;
104     c->revert = current;
105     while (c->revert && !normal(c->revert))
106         c->revert = c->revert->revert;
107     current = c;
108 #ifdef  DEBUG
109     if (debug)
110         dump_revert();
111 #endif
112 }
113 
114 void
nofocus()115 nofocus()
116 {
117     static Window w = 0;
118     int mask;
119     XSetWindowAttributes attr;
120     Client *c;
121 
122     if (current) {
123         setactive(current, 0);
124         for (c = current->revert; c; c = c->revert)
125             if (normal(c)) {
126                 active(c);
127                 return;
128             }
129         /* if no candidates to revert to, fall through */
130     }
131     current = 0;
132     if (w == 0) {
133         mask = CWOverrideRedirect;
134         attr.override_redirect = 1;
135         w = XCreateWindow(dpy, root, 0, 0, 1, 1, 0, CopyFromParent,
136             InputOnly, CopyFromParent, mask, &attr);
137         XMapWindow(dpy, w);
138     }
139     XSetInputFocus(dpy, w, RevertToPointerRoot, timestamp());
140     cmapfocus(0);
141 }
142 
143 Client *
getclient(w,create)144 getclient(w, create)
145 Window w;
146 int create;
147 {
148     Client *c;
149 
150     if (w == 0 || w == root)
151         return 0;
152 
153     for (c = clients; c; c = c->next)
154         if (c->window == w || c->parent == w)
155             return c;
156 
157     if (!create)
158         return 0;
159 
160     c = (Client *)malloc(sizeof(Client));
161     memset(c, 0, sizeof(Client));
162     c->window = w;
163     c->parent = root;
164     c->reparenting = 0;
165     c->state = WithdrawnState;
166     c->init = 0;
167     c->cmap = None;
168     c->label = c->class = 0;
169     c->revert = 0;
170     c->is9term = 0;
171     c->hold = 0;
172     c->ncmapwins = 0;
173     c->cmapwins = 0;
174     c->wmcmaps = 0;
175     c->next = clients;
176     c->virtual = virtual;
177     clients = c;
178     return c;
179 }
180 
181 void
rmclient(c)182 rmclient(c)
183 Client *c;
184 {
185     Client *cc;
186 
187     for (cc = current; cc && cc->revert; cc = cc->revert)
188         if (cc->revert == c)
189             cc->revert = cc->revert->revert;
190 
191     if (c == clients)
192         clients = c->next;
193     for (cc = clients; cc && cc->next; cc = cc->next)
194         if (cc->next == c)
195             cc->next = cc->next->next;
196 
197     if (hidden(c))
198         unhidec(c, 0);
199 
200     if (c->parent != root)
201         XDestroyWindow(dpy, c->parent);
202 
203     c->parent = c->window = None;       /* paranoia */
204     if (current == c) {
205         current = c->revert;
206         if (current == 0)
207             nofocus();
208         else
209             setactive(current, 1);
210     }
211     if (c->ncmapwins != 0) {
212         XFree((char *)c->cmapwins);
213         free((char *)c->wmcmaps);
214     }
215     if (c->iconname != 0)
216         XFree((char*) c->iconname);
217     if (c->name != 0)
218         XFree((char*) c->name);
219     if (c->instance != 0)
220         XFree((char*) c->instance);
221     if (c->class != 0)
222         XFree((char*) c->class);
223     memset(c, 0, sizeof(Client));       /* paranoia */
224     free(c);
225 }
226