aewl

view client.c @ 73:c2ddb9dbbd10

rearranged
author Anselm R. Garbe <garbeam@wmii.de>
date Fri, 14 Jul 2006 22:33:38 +0200
parents 7681ef838201
children 5370ef170cc9
line source
1 /*
2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 * See LICENSE file for license details.
4 */
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <X11/Xatom.h>
10 #include <X11/Xutil.h>
12 #include "dwm.h"
14 static Rule rule[] = {
15 /* class instance tags floating */
16 { "Firefox-bin", "Gecko", { [Twww] = "www" }, False },
17 };
19 Client *
20 next(Client *c)
21 {
22 for(; c && !c->tags[tsel]; c = c->next);
23 return c;
24 }
26 void
27 ban_client(Client *c)
28 {
29 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
30 XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty);
31 }
33 static void
34 resize_title(Client *c)
35 {
36 int i;
38 c->tw = 0;
39 for(i = 0; i < TLast; i++)
40 if(c->tags[i])
41 c->tw += textw(c->tags[i]);
42 c->tw += textw(c->name);
43 if(c->tw > c->w)
44 c->tw = c->w + 2;
45 c->tx = c->x + c->w - c->tw + 2;
46 c->ty = c->y;
47 XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th);
48 }
50 void
51 update_name(Client *c)
52 {
53 XTextProperty name;
54 int n;
55 char **list = NULL;
57 name.nitems = 0;
58 c->name[0] = 0;
59 XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]);
60 if(!name.nitems)
61 XGetWMName(dpy, c->win, &name);
62 if(!name.nitems)
63 return;
64 if(name.encoding == XA_STRING)
65 strncpy(c->name, (char *)name.value, sizeof(c->name));
66 else {
67 if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
68 && n > 0 && *list)
69 {
70 strncpy(c->name, *list, sizeof(c->name));
71 XFreeStringList(list);
72 }
73 }
74 XFree(name.value);
75 resize_title(c);
76 }
78 void
79 update_size(Client *c)
80 {
81 XSizeHints size;
82 long msize;
83 if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags)
84 size.flags = PSize;
85 c->flags = size.flags;
86 if(c->flags & PBaseSize) {
87 c->basew = size.base_width;
88 c->baseh = size.base_height;
89 }
90 else
91 c->basew = c->baseh = 0;
92 if(c->flags & PResizeInc) {
93 c->incw = size.width_inc;
94 c->inch = size.height_inc;
95 }
96 else
97 c->incw = c->inch = 0;
98 if(c->flags & PMaxSize) {
99 c->maxw = size.max_width;
100 c->maxh = size.max_height;
101 }
102 else
103 c->maxw = c->maxh = 0;
104 if(c->flags & PMinSize) {
105 c->minw = size.min_width;
106 c->minh = size.min_height;
107 }
108 else
109 c->minw = c->minh = 0;
110 if(c->flags & PWinGravity)
111 c->grav = size.win_gravity;
112 else
113 c->grav = NorthWestGravity;
114 }
116 void
117 craise(Client *c)
118 {
119 XRaiseWindow(dpy, c->win);
120 XRaiseWindow(dpy, c->title);
121 }
123 void
124 lower(Client *c)
125 {
126 XLowerWindow(dpy, c->title);
127 XLowerWindow(dpy, c->win);
128 }
130 void
131 focus(Client *c)
132 {
133 Client *old = sel;
134 XEvent ev;
136 XFlush(dpy);
137 sel = c;
138 if(old && old != c)
139 draw_client(old);
140 draw_client(c);
141 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
142 XFlush(dpy);
143 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
144 }
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;
154 if(!len) {
155 c->tags[tsel] = tags[tsel];
156 return;
157 }
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 }
178 if(!matched)
179 c->tags[tsel] = tags[tsel];
180 }
182 void
183 manage(Window w, XWindowAttributes *wa)
184 {
185 Client *c, **l;
186 XSetWindowAttributes twa;
187 Window trans;
189 c = emallocz(sizeof(Client));
190 c->win = w;
191 c->tx = c->x = wa->x;
192 c->ty = c->y = wa->y;
193 if(c->y < bh)
194 c->ty = c->y += bh;
195 c->tw = c->w = wa->width;
196 c->h = wa->height;
197 c->th = bh;
198 c->border = 1;
199 c->proto = win_proto(c->win);
200 update_size(c);
201 XSelectInput(dpy, c->win,
202 StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
203 XGetTransientForHint(dpy, c->win, &trans);
204 twa.override_redirect = 1;
205 twa.background_pixmap = ParentRelative;
206 twa.event_mask = ExposureMask;
208 c->title = XCreateWindow(dpy, root, c->tx, c->ty, c->tw, c->th,
209 0, DefaultDepth(dpy, screen), CopyFromParent,
210 DefaultVisual(dpy, screen),
211 CWOverrideRedirect | CWBackPixmap | CWEventMask, &twa);
213 update_name(c);
214 init_tags(c);
216 for(l = &clients; *l; l = &(*l)->next);
217 c->next = *l; /* *l == nil */
218 *l = c;
220 XGrabButton(dpy, Button1, Mod1Mask, c->win, False, ButtonPressMask,
221 GrabModeAsync, GrabModeSync, None, None);
222 XGrabButton(dpy, Button2, Mod1Mask, c->win, False, ButtonPressMask,
223 GrabModeAsync, GrabModeSync, None, None);
224 XGrabButton(dpy, Button3, Mod1Mask, c->win, False, ButtonPressMask,
225 GrabModeAsync, GrabModeSync, None, None);
227 if(!c->floating)
228 c->floating = trans
229 || ((c->maxw == c->minw) && (c->maxh == c->minh));
231 arrange(NULL);
232 /* mapping the window now prevents flicker */
233 if(c->tags[tsel]) {
234 XMapRaised(dpy, c->win);
235 XMapRaised(dpy, c->title);
236 focus(c);
237 }
238 else {
239 ban_client(c);
240 XMapRaised(dpy, c->win);
241 XMapRaised(dpy, c->title);
242 }
243 }
245 void
246 gravitate(Client *c, Bool invert)
247 {
248 int dx = 0, dy = 0;
250 switch(c->grav) {
251 case StaticGravity:
252 case NorthWestGravity:
253 case NorthGravity:
254 case NorthEastGravity:
255 dy = c->border;
256 break;
257 case EastGravity:
258 case CenterGravity:
259 case WestGravity:
260 dy = -(c->h / 2) + c->border;
261 break;
262 case SouthEastGravity:
263 case SouthGravity:
264 case SouthWestGravity:
265 dy = -c->h;
266 break;
267 default:
268 break;
269 }
271 switch (c->grav) {
272 case StaticGravity:
273 case NorthWestGravity:
274 case WestGravity:
275 case SouthWestGravity:
276 dx = c->border;
277 break;
278 case NorthGravity:
279 case CenterGravity:
280 case SouthGravity:
281 dx = -(c->w / 2) + c->border;
282 break;
283 case NorthEastGravity:
284 case EastGravity:
285 case SouthEastGravity:
286 dx = -(c->w + c->border);
287 break;
288 default:
289 break;
290 }
292 if(invert) {
293 dx = -dx;
294 dy = -dy;
295 }
296 c->x += dx;
297 c->y += dy;
298 }
301 void
302 resize(Client *c, Bool inc)
303 {
304 XConfigureEvent e;
306 if(inc) {
307 if(c->incw)
308 c->w -= (c->w - c->basew) % c->incw;
309 if(c->inch)
310 c->h -= (c->h - c->baseh) % c->inch;
311 }
312 if(c->x > sw) /* might happen on restart */
313 c->x = sw - c->w;
314 if(c->y > sh)
315 c->ty = c->y = sh - c->h;
316 if(c->minw && c->w < c->minw)
317 c->w = c->minw;
318 if(c->minh && c->h < c->minh)
319 c->h = c->minh;
320 if(c->maxw && c->w > c->maxw)
321 c->w = c->maxw;
322 if(c->maxh && c->h > c->maxh)
323 c->h = c->maxh;
324 resize_title(c);
325 XSetWindowBorderWidth(dpy, c->win, 1);
326 XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
327 e.type = ConfigureNotify;
328 e.event = c->win;
329 e.window = c->win;
330 e.x = c->x;
331 e.y = c->y;
332 e.width = c->w;
333 e.height = c->h;
334 e.border_width = c->border;
335 e.above = None;
336 e.override_redirect = False;
337 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
338 XFlush(dpy);
339 }
341 static int
342 dummy_error_handler(Display *dsply, XErrorEvent *err)
343 {
344 return 0;
345 }
347 void
348 unmanage(Client *c)
349 {
350 Client **l;
352 XGrabServer(dpy);
353 XSetErrorHandler(dummy_error_handler);
355 XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
356 XDestroyWindow(dpy, c->title);
358 for(l = &clients; *l && *l != c; l = &(*l)->next);
359 *l = c->next;
360 for(l = &clients; *l; l = &(*l)->next)
361 if((*l)->revert == c)
362 (*l)->revert = NULL;
363 if(sel == c)
364 sel = sel->revert ? sel->revert : clients;
366 free(c);
368 XFlush(dpy);
369 XSetErrorHandler(error_handler);
370 XUngrabServer(dpy);
371 arrange(NULL);
372 if(sel)
373 focus(sel);
374 }
376 Client *
377 gettitle(Window w)
378 {
379 Client *c;
380 for(c = clients; c; c = c->next)
381 if(c->title == w)
382 return c;
383 return NULL;
384 }
386 Client *
387 getclient(Window w)
388 {
389 Client *c;
390 for(c = clients; c; c = c->next)
391 if(c->win == w)
392 return c;
393 return NULL;
394 }