1 /* See LICENSE file for copyright and license details. */ |
|
2 #include "dwm.h" |
|
3 #include <stdlib.h> |
|
4 #include <string.h> |
|
5 #include <X11/Xatom.h> |
|
6 #include <X11/Xutil.h> |
|
7 |
|
8 /* static */ |
|
9 |
|
10 typedef struct { |
|
11 const char *symbol; |
|
12 void (*arrange)(void); |
|
13 } Layout; |
|
14 |
|
15 unsigned int blw = 0; |
|
16 static char prop[128]; |
|
17 static unsigned int ltidx = 0; /* default */ |
|
18 |
|
19 static void |
|
20 floating(void) { /* default floating layout */ |
|
21 Client *c; |
|
22 |
|
23 for(c = clients; c; c = c->next) |
|
24 if(isvisible(c)) |
|
25 resize(c, c->x, c->y, c->w, c->h, True); |
|
26 } |
|
27 |
|
28 static unsigned int nlayouts = 0; |
|
29 |
|
30 LAYOUTS |
|
31 |
|
32 /* extern */ |
|
33 |
|
34 void |
|
35 arrange(void) { |
|
36 Client *c; |
|
37 |
|
38 for(c = clients; c; c = c->next) |
|
39 if(isvisible(c)) |
|
40 unban(c); |
|
41 else |
|
42 ban(c); |
|
43 layouts[ltidx].arrange(); |
|
44 focus(NULL); |
|
45 restack(); |
|
46 } |
|
47 |
|
48 void |
|
49 focusnext(const char *arg) { |
|
50 Client *c; |
|
51 |
|
52 if(!sel) |
|
53 return; |
|
54 for(c = sel->next; c && !isvisible(c); c = c->next); |
|
55 if(!c) |
|
56 for(c = clients; c && !isvisible(c); c = c->next); |
|
57 if(c) { |
|
58 focus(c); |
|
59 restack(); |
|
60 } |
|
61 } |
|
62 |
|
63 void |
|
64 focusprev(const char *arg) { |
|
65 Client *c; |
|
66 |
|
67 if(!sel) |
|
68 return; |
|
69 for(c = sel->prev; c && !isvisible(c); c = c->prev); |
|
70 if(!c) { |
|
71 for(c = clients; c && c->next; c = c->next); |
|
72 for(; c && !isvisible(c); c = c->prev); |
|
73 } |
|
74 if(c) { |
|
75 focus(c); |
|
76 restack(); |
|
77 } |
|
78 } |
|
79 |
|
80 const char * |
|
81 getsymbol(void) |
|
82 { |
|
83 return layouts[ltidx].symbol; |
|
84 } |
|
85 |
|
86 Bool |
|
87 isfloating(void) { |
|
88 return layouts[ltidx].arrange == floating; |
|
89 } |
|
90 |
|
91 Bool |
|
92 isarrange(void (*func)()) |
|
93 { |
|
94 return func == layouts[ltidx].arrange; |
|
95 } |
|
96 |
|
97 void |
|
98 initlayouts(void) { |
|
99 unsigned int i, w; |
|
100 |
|
101 nlayouts = sizeof layouts / sizeof layouts[0]; |
|
102 for(blw = i = 0; i < nlayouts; i++) { |
|
103 w = textw(layouts[i].symbol); |
|
104 if(w > blw) |
|
105 blw = w; |
|
106 } |
|
107 } |
|
108 |
|
109 void |
|
110 loaddwmprops(void) { |
|
111 unsigned int i; |
|
112 |
|
113 if(gettextprop(root, dwmprops, prop, sizeof prop)) { |
|
114 for(i = 0; i < ntags && i < sizeof prop - 1 && prop[i] != '\0'; i++) |
|
115 seltags[i] = prop[i] == '1'; |
|
116 if(i < sizeof prop - 1 && prop[i] != '\0') { |
|
117 if(prop[i] < nlayouts) |
|
118 ltidx = prop[i]; |
|
119 } |
|
120 } |
|
121 } |
|
122 |
|
123 Client * |
|
124 nexttiled(Client *c) { |
|
125 for(; c && (c->isfloating || !isvisible(c)); c = c->next); |
|
126 return c; |
|
127 } |
|
128 |
|
129 void |
|
130 restack(void) { |
|
131 Client *c; |
|
132 XEvent ev; |
|
133 XWindowChanges wc; |
|
134 |
|
135 drawstatus(); |
|
136 if(!sel) |
|
137 return; |
|
138 if(sel->isfloating || isfloating()) |
|
139 XRaiseWindow(dpy, sel->win); |
|
140 if(!isfloating()) { |
|
141 wc.stack_mode = Below; |
|
142 wc.sibling = barwin; |
|
143 if(!sel->isfloating) { |
|
144 XConfigureWindow(dpy, sel->win, CWSibling | CWStackMode, &wc); |
|
145 wc.sibling = sel->win; |
|
146 } |
|
147 for(c = nexttiled(clients); c; c = nexttiled(c->next)) { |
|
148 if(c == sel) |
|
149 continue; |
|
150 XConfigureWindow(dpy, c->win, CWSibling | CWStackMode, &wc); |
|
151 wc.sibling = c->win; |
|
152 } |
|
153 } |
|
154 XSync(dpy, False); |
|
155 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
|
156 } |
|
157 |
|
158 void |
|
159 savedwmprops(void) { |
|
160 unsigned int i; |
|
161 |
|
162 for(i = 0; i < ntags && i < sizeof prop - 1; i++) |
|
163 prop[i] = seltags[i] ? '1' : '0'; |
|
164 if(i < sizeof prop - 1) |
|
165 prop[i++] = (char)ltidx; |
|
166 prop[i] = '\0'; |
|
167 XChangeProperty(dpy, root, dwmprops, XA_STRING, 8, |
|
168 PropModeReplace, (unsigned char *)prop, i); |
|
169 } |
|
170 |
|
171 void |
|
172 setlayout(const char *arg) { |
|
173 int i; |
|
174 |
|
175 if(!arg) { |
|
176 if(++ltidx == nlayouts) |
|
177 ltidx = 0;; |
|
178 } |
|
179 else { |
|
180 i = atoi(arg); |
|
181 if(i < 0 || i >= nlayouts) |
|
182 return; |
|
183 ltidx = i; |
|
184 } |
|
185 if(sel) |
|
186 arrange(); |
|
187 else |
|
188 drawstatus(); |
|
189 savedwmprops(); |
|
190 } |
|
191 |
|
192 void |
|
193 togglebar(const char *arg) { |
|
194 if(bpos == BarOff) |
|
195 bpos = (BARPOS == BarOff) ? BarTop : BARPOS; |
|
196 else |
|
197 bpos = BarOff; |
|
198 updatebarpos(); |
|
199 arrange(); |
|
200 } |
|
201 |
|
202 void |
|
203 togglemax(const char *arg) { |
|
204 XEvent ev; |
|
205 |
|
206 if(!sel || (!isfloating() && !sel->isfloating) || sel->isfixed) |
|
207 return; |
|
208 if((sel->ismax = !sel->ismax)) { |
|
209 sel->rx = sel->x; |
|
210 sel->ry = sel->y; |
|
211 sel->rw = sel->w; |
|
212 sel->rh = sel->h; |
|
213 resize(sel, wax, way, waw - 2 * sel->border, wah - 2 * sel->border, True); |
|
214 } |
|
215 else |
|
216 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True); |
|
217 drawstatus(); |
|
218 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
|
219 } |
|