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