9 #include <X11/Xatom.h> |
9 #include <X11/Xatom.h> |
10 #include <X11/Xutil.h> |
10 #include <X11/Xutil.h> |
11 |
11 |
12 #include "dwm.h" |
12 #include "dwm.h" |
13 |
13 |
14 static Rule rule[] = { |
|
15 /* class instance tags floating */ |
|
16 { "Firefox-bin", "Gecko", { [Twww] = "www" }, False }, |
|
17 }; |
|
18 |
|
19 Client * |
|
20 getnext(Client *c) |
|
21 { |
|
22 for(; c && !c->tags[tsel]; c = c->next); |
|
23 return c; |
|
24 } |
|
25 |
|
26 void |
14 void |
27 ban(Client *c) |
15 ban(Client *c) |
28 { |
16 { |
29 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
17 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
30 XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty); |
18 XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty); |
31 } |
19 } |
32 |
20 |
33 static void |
21 static void |
34 resize_title(Client *c) |
22 resizetitle(Client *c) |
35 { |
23 { |
36 int i; |
24 int i; |
37 |
25 |
38 c->tw = 0; |
26 c->tw = 0; |
39 for(i = 0; i < TLast; i++) |
27 for(i = 0; i < TLast; i++) |
139 drawtitle(old); |
127 drawtitle(old); |
140 drawtitle(c); |
128 drawtitle(c); |
141 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
129 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
142 XFlush(dpy); |
130 XFlush(dpy); |
143 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
131 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
144 } |
|
145 |
|
146 static void |
|
147 init_tags(Client *c) |
|
148 { |
|
149 XClassHint ch; |
|
150 static unsigned int len = rule ? sizeof(rule) / sizeof(rule[0]) : 0; |
|
151 unsigned int i, j; |
|
152 Bool matched = False; |
|
153 |
|
154 if(!len) { |
|
155 c->tags[tsel] = tags[tsel]; |
|
156 return; |
|
157 } |
|
158 |
|
159 if(XGetClassHint(dpy, c->win, &ch)) { |
|
160 if(ch.res_class && ch.res_name) { |
|
161 for(i = 0; i < len; i++) |
|
162 if(!strncmp(rule[i].class, ch.res_class, sizeof(rule[i].class)) |
|
163 && !strncmp(rule[i].instance, ch.res_name, sizeof(rule[i].instance))) |
|
164 { |
|
165 for(j = 0; j < TLast; j++) |
|
166 c->tags[j] = rule[i].tags[j]; |
|
167 c->floating = rule[i].floating; |
|
168 matched = True; |
|
169 break; |
|
170 } |
|
171 } |
|
172 if(ch.res_class) |
|
173 XFree(ch.res_class); |
|
174 if(ch.res_name) |
|
175 XFree(ch.res_name); |
|
176 } |
|
177 |
|
178 if(!matched) |
|
179 c->tags[tsel] = tags[tsel]; |
|
180 } |
132 } |
181 |
133 |
182 void |
134 void |
183 manage(Window w, XWindowAttributes *wa) |
135 manage(Window w, XWindowAttributes *wa) |
184 { |
136 { |
194 c->ty = c->y += bh; |
146 c->ty = c->y += bh; |
195 c->tw = c->w = wa->width; |
147 c->tw = c->w = wa->width; |
196 c->h = wa->height; |
148 c->h = wa->height; |
197 c->th = bh; |
149 c->th = bh; |
198 c->border = 1; |
150 c->border = 1; |
199 c->proto = proto(c->win); |
151 c->proto = getproto(c->win); |
200 setsize(c); |
152 setsize(c); |
201 XSelectInput(dpy, c->win, |
153 XSelectInput(dpy, c->win, |
202 StructureNotifyMask | PropertyChangeMask | EnterWindowMask); |
154 StructureNotifyMask | PropertyChangeMask | EnterWindowMask); |
203 XGetTransientForHint(dpy, c->win, &trans); |
155 XGetTransientForHint(dpy, c->win, &trans); |
204 twa.override_redirect = 1; |
156 twa.override_redirect = 1; |
209 0, DefaultDepth(dpy, screen), CopyFromParent, |
161 0, DefaultDepth(dpy, screen), CopyFromParent, |
210 DefaultVisual(dpy, screen), |
162 DefaultVisual(dpy, screen), |
211 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); |
163 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa); |
212 |
164 |
213 settitle(c); |
165 settitle(c); |
214 init_tags(c); |
166 settags(c); |
215 |
167 |
216 for(l = &clients; *l; l = &(*l)->next); |
168 for(l = &clients; *l; l = &(*l)->next); |
217 c->next = *l; /* *l == nil */ |
169 c->next = *l; /* *l == nil */ |
218 *l = c; |
170 *l = c; |
219 |
171 |
222 XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask, |
174 XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask, |
223 GrabModeAsync, GrabModeSync, None, None); |
175 GrabModeAsync, GrabModeSync, None, None); |
224 XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask, |
176 XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask, |
225 GrabModeAsync, GrabModeSync, None, None); |
177 GrabModeAsync, GrabModeSync, None, None); |
226 |
178 |
227 if(!c->floating) |
179 if(!c->dofloat) |
228 c->floating = trans |
180 c->dofloat = trans |
229 || ((c->maxw == c->minw) && (c->maxh == c->minh)); |
181 || ((c->maxw == c->minw) && (c->maxh == c->minh)); |
230 |
182 |
231 arrange(NULL); |
183 arrange(NULL); |
232 /* mapping the window now prevents flicker */ |
184 /* mapping the window now prevents flicker */ |
233 if(c->tags[tsel]) { |
185 if(c->tags[tsel]) { |
319 c->h = c->minh; |
271 c->h = c->minh; |
320 if(c->maxw && c->w > c->maxw) |
272 if(c->maxw && c->w > c->maxw) |
321 c->w = c->maxw; |
273 c->w = c->maxw; |
322 if(c->maxh && c->h > c->maxh) |
274 if(c->maxh && c->h > c->maxh) |
323 c->h = c->maxh; |
275 c->h = c->maxh; |
324 resize_title(c); |
276 resizetitle(c); |
325 XSetWindowBorderWidth(dpy, c->win, 1); |
277 XSetWindowBorderWidth(dpy, c->win, 1); |
326 XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); |
278 XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h); |
327 e.type = ConfigureNotify; |
279 e.type = ConfigureNotify; |
328 e.event = c->win; |
280 e.event = c->win; |
329 e.window = c->win; |
281 e.window = c->win; |
337 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e); |
289 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e); |
338 XFlush(dpy); |
290 XFlush(dpy); |
339 } |
291 } |
340 |
292 |
341 static int |
293 static int |
342 dummy_xerror(Display *dsply, XErrorEvent *err) |
294 xerrordummy(Display *dsply, XErrorEvent *ee) |
343 { |
295 { |
344 return 0; |
296 return 0; |
345 } |
297 } |
346 |
298 |
347 void |
299 void |
348 unmanage(Client *c) |
300 unmanage(Client *c) |
349 { |
301 { |
350 Client **l; |
302 Client **l; |
351 |
303 |
352 XGrabServer(dpy); |
304 XGrabServer(dpy); |
353 XSetErrorHandler(dummy_xerror); |
305 XSetErrorHandler(xerrordummy); |
354 |
306 |
355 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
307 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
356 XDestroyWindow(dpy, c->title); |
308 XDestroyWindow(dpy, c->title); |
357 |
309 |
358 for(l = &clients; *l && *l != c; l = &(*l)->next); |
310 for(l = &clients; *l && *l != c; l = &(*l)->next); |
390 for(c = clients; c; c = c->next) |
342 for(c = clients; c; c = c->next) |
391 if(c->win == w) |
343 if(c->win == w) |
392 return c; |
344 return c; |
393 return NULL; |
345 return NULL; |
394 } |
346 } |
|
347 |
|
348 void |
|
349 zoom(Arg *arg) |
|
350 { |
|
351 Client **l, *c; |
|
352 |
|
353 if(!sel) |
|
354 return; |
|
355 |
|
356 if(sel == getnext(clients) && sel->next) { |
|
357 if((c = getnext(sel->next))) |
|
358 sel = c; |
|
359 } |
|
360 |
|
361 for(l = &clients; *l && *l != sel; l = &(*l)->next); |
|
362 *l = sel->next; |
|
363 |
|
364 sel->next = clients; /* pop */ |
|
365 clients = sel; |
|
366 arrange(NULL); |
|
367 focus(sel); |
|
368 } |
|
369 |
|
370 void |
|
371 maximize(Arg *arg) |
|
372 { |
|
373 if(!sel) |
|
374 return; |
|
375 sel->x = sx; |
|
376 sel->y = sy + bh; |
|
377 sel->w = sw - 2 * sel->border; |
|
378 sel->h = sh - 2 * sel->border - bh; |
|
379 higher(sel); |
|
380 resize(sel, False); |
|
381 } |
|
382 |
|
383 void |
|
384 focusprev(Arg *arg) |
|
385 { |
|
386 Client *c; |
|
387 |
|
388 if(!sel) |
|
389 return; |
|
390 |
|
391 if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) { |
|
392 higher(c); |
|
393 focus(c); |
|
394 } |
|
395 } |
|
396 |
|
397 void |
|
398 focusnext(Arg *arg) |
|
399 { |
|
400 Client *c; |
|
401 |
|
402 if(!sel) |
|
403 return; |
|
404 |
|
405 if(!(c = getnext(sel->next))) |
|
406 c = getnext(clients); |
|
407 if(c) { |
|
408 higher(c); |
|
409 c->revert = sel; |
|
410 focus(c); |
|
411 } |
|
412 } |
|
413 |
|
414 void |
|
415 killclient(Arg *arg) |
|
416 { |
|
417 if(!sel) |
|
418 return; |
|
419 if(sel->proto & WM_PROTOCOL_DELWIN) |
|
420 sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]); |
|
421 else |
|
422 XKillClient(dpy, sel->win); |
|
423 } |