1 /* |
1 /* |
2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> |
2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> |
3 * See LICENSE file for license details. |
3 * See LICENSE file for license details. |
4 */ |
4 */ |
|
5 #include "dwm.h" |
5 |
6 |
6 #include <stdlib.h> |
7 #include <stdlib.h> |
7 #include <stdio.h> |
|
8 #include <string.h> |
8 #include <string.h> |
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 /* static functions */ |
13 |
|
14 void |
|
15 ban(Client *c) |
|
16 { |
|
17 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
|
18 XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty); |
|
19 } |
|
20 |
13 |
21 static void |
14 static void |
22 resizetitle(Client *c) |
15 resizetitle(Client *c) |
23 { |
16 { |
24 int i; |
17 int i; |
33 c->tx = c->x + c->w - c->tw + 2; |
26 c->tx = c->x + c->w - c->tw + 2; |
34 c->ty = c->y; |
27 c->ty = c->y; |
35 XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th); |
28 XMoveResizeWindow(dpy, c->title, c->tx, c->ty, c->tw, c->th); |
36 } |
29 } |
37 |
30 |
38 void |
31 static int |
39 settitle(Client *c) |
32 xerrordummy(Display *dsply, XErrorEvent *ee) |
40 { |
33 { |
41 XTextProperty name; |
34 return 0; |
42 int n; |
35 } |
43 char **list = NULL; |
36 |
44 |
37 /* extern functions */ |
45 name.nitems = 0; |
38 |
46 c->name[0] = 0; |
39 void |
47 XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]); |
40 ban(Client *c) |
48 if(!name.nitems) |
41 { |
49 XGetWMName(dpy, c->win, &name); |
42 XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y); |
50 if(!name.nitems) |
43 XMoveWindow(dpy, c->title, c->tx + 2 * sw, c->ty); |
51 return; |
|
52 if(name.encoding == XA_STRING) |
|
53 strncpy(c->name, (char *)name.value, sizeof(c->name)); |
|
54 else { |
|
55 if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success |
|
56 && n > 0 && *list) |
|
57 { |
|
58 strncpy(c->name, *list, sizeof(c->name)); |
|
59 XFreeStringList(list); |
|
60 } |
|
61 } |
|
62 XFree(name.value); |
|
63 resizetitle(c); |
|
64 } |
|
65 |
|
66 void |
|
67 setsize(Client *c) |
|
68 { |
|
69 XSizeHints size; |
|
70 long msize; |
|
71 if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) |
|
72 size.flags = PSize; |
|
73 c->flags = size.flags; |
|
74 if(c->flags & PBaseSize) { |
|
75 c->basew = size.base_width; |
|
76 c->baseh = size.base_height; |
|
77 } |
|
78 else |
|
79 c->basew = c->baseh = 0; |
|
80 if(c->flags & PResizeInc) { |
|
81 c->incw = size.width_inc; |
|
82 c->inch = size.height_inc; |
|
83 } |
|
84 else |
|
85 c->incw = c->inch = 0; |
|
86 if(c->flags & PMaxSize) { |
|
87 c->maxw = size.max_width; |
|
88 c->maxh = size.max_height; |
|
89 } |
|
90 else |
|
91 c->maxw = c->maxh = 0; |
|
92 if(c->flags & PMinSize) { |
|
93 c->minw = size.min_width; |
|
94 c->minh = size.min_height; |
|
95 } |
|
96 else |
|
97 c->minw = c->minh = 0; |
|
98 if(c->flags & PWinGravity) |
|
99 c->grav = size.win_gravity; |
|
100 else |
|
101 c->grav = NorthWestGravity; |
|
102 } |
|
103 |
|
104 void |
|
105 higher(Client *c) |
|
106 { |
|
107 XRaiseWindow(dpy, c->win); |
|
108 XRaiseWindow(dpy, c->title); |
|
109 } |
|
110 |
|
111 void |
|
112 lower(Client *c) |
|
113 { |
|
114 XLowerWindow(dpy, c->title); |
|
115 XLowerWindow(dpy, c->win); |
|
116 } |
44 } |
117 |
45 |
118 void |
46 void |
119 focus(Client *c) |
47 focus(Client *c) |
120 { |
48 { |
127 drawtitle(old); |
55 drawtitle(old); |
128 drawtitle(c); |
56 drawtitle(c); |
129 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
57 XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
130 XFlush(dpy); |
58 XFlush(dpy); |
131 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
59 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
|
60 } |
|
61 |
|
62 void |
|
63 focusnext(Arg *arg) |
|
64 { |
|
65 Client *c; |
|
66 |
|
67 if(!sel) |
|
68 return; |
|
69 |
|
70 if(!(c = getnext(sel->next))) |
|
71 c = getnext(clients); |
|
72 if(c) { |
|
73 higher(c); |
|
74 c->revert = sel; |
|
75 focus(c); |
|
76 } |
|
77 } |
|
78 |
|
79 void |
|
80 focusprev(Arg *arg) |
|
81 { |
|
82 Client *c; |
|
83 |
|
84 if(!sel) |
|
85 return; |
|
86 |
|
87 if((c = sel->revert && sel->revert->tags[tsel] ? sel->revert : NULL)) { |
|
88 higher(c); |
|
89 focus(c); |
|
90 } |
|
91 } |
|
92 |
|
93 Client * |
|
94 getclient(Window w) |
|
95 { |
|
96 Client *c; |
|
97 for(c = clients; c; c = c->next) |
|
98 if(c->win == w) |
|
99 return c; |
|
100 return NULL; |
|
101 } |
|
102 |
|
103 Client * |
|
104 getctitle(Window w) |
|
105 { |
|
106 Client *c; |
|
107 for(c = clients; c; c = c->next) |
|
108 if(c->title == w) |
|
109 return c; |
|
110 return NULL; |
|
111 } |
|
112 |
|
113 void |
|
114 gravitate(Client *c, Bool invert) |
|
115 { |
|
116 int dx = 0, dy = 0; |
|
117 |
|
118 switch(c->grav) { |
|
119 case StaticGravity: |
|
120 case NorthWestGravity: |
|
121 case NorthGravity: |
|
122 case NorthEastGravity: |
|
123 dy = c->border; |
|
124 break; |
|
125 case EastGravity: |
|
126 case CenterGravity: |
|
127 case WestGravity: |
|
128 dy = -(c->h / 2) + c->border; |
|
129 break; |
|
130 case SouthEastGravity: |
|
131 case SouthGravity: |
|
132 case SouthWestGravity: |
|
133 dy = -c->h; |
|
134 break; |
|
135 default: |
|
136 break; |
|
137 } |
|
138 |
|
139 switch (c->grav) { |
|
140 case StaticGravity: |
|
141 case NorthWestGravity: |
|
142 case WestGravity: |
|
143 case SouthWestGravity: |
|
144 dx = c->border; |
|
145 break; |
|
146 case NorthGravity: |
|
147 case CenterGravity: |
|
148 case SouthGravity: |
|
149 dx = -(c->w / 2) + c->border; |
|
150 break; |
|
151 case NorthEastGravity: |
|
152 case EastGravity: |
|
153 case SouthEastGravity: |
|
154 dx = -(c->w + c->border); |
|
155 break; |
|
156 default: |
|
157 break; |
|
158 } |
|
159 |
|
160 if(invert) { |
|
161 dx = -dx; |
|
162 dy = -dy; |
|
163 } |
|
164 c->x += dx; |
|
165 c->y += dy; |
|
166 } |
|
167 |
|
168 void |
|
169 higher(Client *c) |
|
170 { |
|
171 XRaiseWindow(dpy, c->win); |
|
172 XRaiseWindow(dpy, c->title); |
|
173 } |
|
174 |
|
175 void |
|
176 killclient(Arg *arg) |
|
177 { |
|
178 if(!sel) |
|
179 return; |
|
180 if(sel->proto & WM_PROTOCOL_DELWIN) |
|
181 sendevent(sel->win, wm_atom[WMProtocols], wm_atom[WMDelete]); |
|
182 else |
|
183 XKillClient(dpy, sel->win); |
|
184 } |
|
185 |
|
186 void |
|
187 lower(Client *c) |
|
188 { |
|
189 XLowerWindow(dpy, c->title); |
|
190 XLowerWindow(dpy, c->win); |
132 } |
191 } |
133 |
192 |
134 void |
193 void |
135 manage(Window w, XWindowAttributes *wa) |
194 manage(Window w, XWindowAttributes *wa) |
136 { |
195 { |
193 XMapRaised(dpy, c->title); |
252 XMapRaised(dpy, c->title); |
194 } |
253 } |
195 } |
254 } |
196 |
255 |
197 void |
256 void |
198 gravitate(Client *c, Bool invert) |
257 maximize(Arg *arg) |
199 { |
258 { |
200 int dx = 0, dy = 0; |
259 if(!sel) |
201 |
260 return; |
202 switch(c->grav) { |
261 sel->x = sx; |
203 case StaticGravity: |
262 sel->y = sy + bh; |
204 case NorthWestGravity: |
263 sel->w = sw - 2 * sel->border; |
205 case NorthGravity: |
264 sel->h = sh - 2 * sel->border - bh; |
206 case NorthEastGravity: |
265 higher(sel); |
207 dy = c->border; |
266 resize(sel, False); |
208 break; |
267 } |
209 case EastGravity: |
|
210 case CenterGravity: |
|
211 case WestGravity: |
|
212 dy = -(c->h / 2) + c->border; |
|
213 break; |
|
214 case SouthEastGravity: |
|
215 case SouthGravity: |
|
216 case SouthWestGravity: |
|
217 dy = -c->h; |
|
218 break; |
|
219 default: |
|
220 break; |
|
221 } |
|
222 |
|
223 switch (c->grav) { |
|
224 case StaticGravity: |
|
225 case NorthWestGravity: |
|
226 case WestGravity: |
|
227 case SouthWestGravity: |
|
228 dx = c->border; |
|
229 break; |
|
230 case NorthGravity: |
|
231 case CenterGravity: |
|
232 case SouthGravity: |
|
233 dx = -(c->w / 2) + c->border; |
|
234 break; |
|
235 case NorthEastGravity: |
|
236 case EastGravity: |
|
237 case SouthEastGravity: |
|
238 dx = -(c->w + c->border); |
|
239 break; |
|
240 default: |
|
241 break; |
|
242 } |
|
243 |
|
244 if(invert) { |
|
245 dx = -dx; |
|
246 dy = -dy; |
|
247 } |
|
248 c->x += dx; |
|
249 c->y += dy; |
|
250 } |
|
251 |
|
252 |
268 |
253 void |
269 void |
254 resize(Client *c, Bool inc) |
270 resize(Client *c, Bool inc) |
255 { |
271 { |
256 XConfigureEvent e; |
272 XConfigureEvent e; |
288 e.override_redirect = False; |
304 e.override_redirect = False; |
289 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e); |
305 XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e); |
290 XFlush(dpy); |
306 XFlush(dpy); |
291 } |
307 } |
292 |
308 |
293 static int |
309 void |
294 xerrordummy(Display *dsply, XErrorEvent *ee) |
310 setsize(Client *c) |
295 { |
311 { |
296 return 0; |
312 XSizeHints size; |
|
313 long msize; |
|
314 if(!XGetWMNormalHints(dpy, c->win, &size, &msize) || !size.flags) |
|
315 size.flags = PSize; |
|
316 c->flags = size.flags; |
|
317 if(c->flags & PBaseSize) { |
|
318 c->basew = size.base_width; |
|
319 c->baseh = size.base_height; |
|
320 } |
|
321 else |
|
322 c->basew = c->baseh = 0; |
|
323 if(c->flags & PResizeInc) { |
|
324 c->incw = size.width_inc; |
|
325 c->inch = size.height_inc; |
|
326 } |
|
327 else |
|
328 c->incw = c->inch = 0; |
|
329 if(c->flags & PMaxSize) { |
|
330 c->maxw = size.max_width; |
|
331 c->maxh = size.max_height; |
|
332 } |
|
333 else |
|
334 c->maxw = c->maxh = 0; |
|
335 if(c->flags & PMinSize) { |
|
336 c->minw = size.min_width; |
|
337 c->minh = size.min_height; |
|
338 } |
|
339 else |
|
340 c->minw = c->minh = 0; |
|
341 if(c->flags & PWinGravity) |
|
342 c->grav = size.win_gravity; |
|
343 else |
|
344 c->grav = NorthWestGravity; |
|
345 } |
|
346 |
|
347 void |
|
348 settitle(Client *c) |
|
349 { |
|
350 XTextProperty name; |
|
351 int n; |
|
352 char **list = NULL; |
|
353 |
|
354 name.nitems = 0; |
|
355 c->name[0] = 0; |
|
356 XGetTextProperty(dpy, c->win, &name, net_atom[NetWMName]); |
|
357 if(!name.nitems) |
|
358 XGetWMName(dpy, c->win, &name); |
|
359 if(!name.nitems) |
|
360 return; |
|
361 if(name.encoding == XA_STRING) |
|
362 strncpy(c->name, (char *)name.value, sizeof(c->name)); |
|
363 else { |
|
364 if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success |
|
365 && n > 0 && *list) |
|
366 { |
|
367 strncpy(c->name, *list, sizeof(c->name)); |
|
368 XFreeStringList(list); |
|
369 } |
|
370 } |
|
371 XFree(name.value); |
|
372 resizetitle(c); |
297 } |
373 } |
298 |
374 |
299 void |
375 void |
300 unmanage(Client *c) |
376 unmanage(Client *c) |
301 { |
377 { |