changeset 1224 | 47496de04028 |
parent 1223 | cd9fd0986555 |
child 1225 | 6211d430f5da |
1223:cd9fd0986555 | 1224:47496de04028 |
---|---|
49 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) |
49 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) |
50 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) |
50 #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask)) |
51 #define LENGTH(x) (sizeof x / sizeof x[0]) |
51 #define LENGTH(x) (sizeof x / sizeof x[0]) |
52 #define MAXTAGLEN 16 |
52 #define MAXTAGLEN 16 |
53 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) |
53 #define MOUSEMASK (BUTTONMASK|PointerMotionMask) |
54 #define TAGMASK ((int)((1LL << LENGTH(tags)) - 1)) |
|
54 |
55 |
55 /* enums */ |
56 /* enums */ |
56 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
57 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
57 enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ |
58 enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ |
58 enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ |
59 enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */ |
66 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
67 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
67 int minax, maxax, minay, maxay; |
68 int minax, maxax, minay, maxay; |
68 long flags; |
69 long flags; |
69 unsigned int bw, oldbw; |
70 unsigned int bw, oldbw; |
70 Bool isbanned, isfixed, isfloating, isurgent; |
71 Bool isbanned, isfixed, isfloating, isurgent; |
71 Bool *tags; |
72 unsigned int tags; |
72 Client *next; |
73 Client *next; |
73 Client *prev; |
74 Client *prev; |
74 Client *snext; |
75 Client *snext; |
75 Window win; |
76 Window win; |
76 }; |
77 }; |
91 } DC; /* draw context */ |
92 } DC; /* draw context */ |
92 |
93 |
93 typedef struct { |
94 typedef struct { |
94 unsigned long mod; |
95 unsigned long mod; |
95 KeySym keysym; |
96 KeySym keysym; |
96 void (*func)(const char *arg); |
97 void (*func)(void *arg); |
97 const char *arg; |
98 void *arg; |
98 } Key; |
99 } Key; |
99 |
100 |
100 typedef struct { |
101 typedef struct { |
101 const char *symbol; |
102 const char *symbol; |
102 void (*arrange)(void); |
103 void (*arrange)(void); |
105 |
106 |
106 typedef struct { |
107 typedef struct { |
107 const char *class; |
108 const char *class; |
108 const char *instance; |
109 const char *instance; |
109 const char *title; |
110 const char *title; |
110 const char *tag; |
111 unsigned int tags; |
111 Bool isfloating; |
112 Bool isfloating; |
112 } Rule; |
113 } Rule; |
113 |
114 |
114 /* function declarations */ |
115 /* function declarations */ |
115 void applyrules(Client *c); |
116 void applyrules(Client *c); |
133 void enternotify(XEvent *e); |
134 void enternotify(XEvent *e); |
134 void eprint(const char *errstr, ...); |
135 void eprint(const char *errstr, ...); |
135 void expose(XEvent *e); |
136 void expose(XEvent *e); |
136 void focus(Client *c); |
137 void focus(Client *c); |
137 void focusin(XEvent *e); |
138 void focusin(XEvent *e); |
138 void focusnext(const char *arg); |
139 void focusnext(void *arg); |
139 void focusprev(const char *arg); |
140 void focusprev(void *arg); |
140 Client *getclient(Window w); |
141 Client *getclient(Window w); |
141 unsigned long getcolor(const char *colstr); |
142 unsigned long getcolor(const char *colstr); |
142 long getstate(Window w); |
143 long getstate(Window w); |
143 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
144 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
144 void grabbuttons(Client *c, Bool focused); |
145 void grabbuttons(Client *c, Bool focused); |
145 void grabkeys(void); |
146 void grabkeys(void); |
146 unsigned int idxoftag(const char *t); |
|
147 void initfont(const char *fontstr); |
147 void initfont(const char *fontstr); |
148 Bool isoccupied(unsigned int t); |
148 Bool isoccupied(unsigned int t); |
149 Bool isprotodel(Client *c); |
149 Bool isprotodel(Client *c); |
150 Bool isurgent(unsigned int t); |
150 Bool isurgent(unsigned int t); |
151 Bool isvisible(Client *c); |
151 Bool isvisible(Client *c); |
152 void keypress(XEvent *e); |
152 void keypress(XEvent *e); |
153 void killclient(const char *arg); |
153 void killclient(void *arg); |
154 void manage(Window w, XWindowAttributes *wa); |
154 void manage(Window w, XWindowAttributes *wa); |
155 void mappingnotify(XEvent *e); |
155 void mappingnotify(XEvent *e); |
156 void maprequest(XEvent *e); |
156 void maprequest(XEvent *e); |
157 void movemouse(Client *c); |
157 void movemouse(Client *c); |
158 Client *nextunfloating(Client *c); |
158 Client *nextunfloating(Client *c); |
159 void propertynotify(XEvent *e); |
159 void propertynotify(XEvent *e); |
160 void quit(const char *arg); |
160 void quit(void *arg); |
161 void resize(Client *c, int x, int y, int w, int h, Bool sizehints); |
161 void resize(Client *c, int x, int y, int w, int h, Bool sizehints); |
162 void resizemouse(Client *c); |
162 void resizemouse(Client *c); |
163 void restack(void); |
163 void restack(void); |
164 void run(void); |
164 void run(void); |
165 void scan(void); |
165 void scan(void); |
166 void setclientstate(Client *c, long state); |
166 void setclientstate(Client *c, long state); |
167 void setmfact(const char *arg); |
167 void setmfact(void *arg); |
168 void setup(void); |
168 void setup(void); |
169 void spawn(const char *arg); |
169 void spawn(void *arg); |
170 void tag(const char *arg); |
170 void tag(void *arg); |
171 unsigned int textnw(const char *text, unsigned int len); |
171 unsigned int textnw(const char *text, unsigned int len); |
172 unsigned int textw(const char *text); |
172 unsigned int textw(const char *text); |
173 void tile(void); |
173 void tile(void); |
174 void tileresize(Client *c, int x, int y, int w, int h); |
174 void tileresize(Client *c, int x, int y, int w, int h); |
175 void togglebar(const char *arg); |
175 void togglebar(void *arg); |
176 void togglefloating(const char *arg); |
176 void togglefloating(void *arg); |
177 void togglelayout(const char *arg); |
177 void togglelayout(void *arg); |
178 void toggletag(const char *arg); |
178 void toggletag(void *arg); |
179 void toggleview(const char *arg); |
179 void toggleview(void *arg); |
180 void unban(Client *c); |
180 void unban(Client *c); |
181 void unmanage(Client *c); |
181 void unmanage(Client *c); |
182 void unmapnotify(XEvent *e); |
182 void unmapnotify(XEvent *e); |
183 void updatebar(void); |
183 void updatebar(void); |
184 void updategeom(void); |
184 void updategeom(void); |
185 void updatesizehints(Client *c); |
185 void updatesizehints(Client *c); |
186 void updatetilegeom(void); |
186 void updatetilegeom(void); |
187 void updatetitle(Client *c); |
187 void updatetitle(Client *c); |
188 void updatewmhints(Client *c); |
188 void updatewmhints(Client *c); |
189 void view(const char *arg); |
189 void view(void *arg); |
190 void viewprevtag(const char *arg); |
190 void viewprevtag(void *arg); |
191 int xerror(Display *dpy, XErrorEvent *ee); |
191 int xerror(Display *dpy, XErrorEvent *ee); |
192 int xerrordummy(Display *dpy, XErrorEvent *ee); |
192 int xerrordummy(Display *dpy, XErrorEvent *ee); |
193 int xerrorstart(Display *dpy, XErrorEvent *ee); |
193 int xerrorstart(Display *dpy, XErrorEvent *ee); |
194 void zoom(const char *arg); |
194 void zoom(void *arg); |
195 |
195 |
196 /* variables */ |
196 /* variables */ |
197 char stext[256]; |
197 char stext[256]; |
198 int screen, sx, sy, sw, sh; |
198 int screen, sx, sy, sw, sh; |
199 int bx, by, bw, bh, blw, wx, wy, ww, wh; |
199 int bx, by, bw, bh, blw, wx, wy, ww, wh; |
200 int mx, my, mw, mh, tx, ty, tw, th; |
200 int mx, my, mw, mh, tx, ty, tw, th; |
201 int seltags = 0; |
201 unsigned int seltags = 0; |
202 int (*xerrorxlib)(Display *, XErrorEvent *); |
202 int (*xerrorxlib)(Display *, XErrorEvent *); |
203 unsigned int numlockmask = 0; |
203 unsigned int numlockmask = 0; |
204 void (*handler[LASTEvent]) (XEvent *) = { |
204 void (*handler[LASTEvent]) (XEvent *) = { |
205 [ButtonPress] = buttonpress, |
205 [ButtonPress] = buttonpress, |
206 [ConfigureRequest] = configurerequest, |
206 [ConfigureRequest] = configurerequest, |
216 [UnmapNotify] = unmapnotify |
216 [UnmapNotify] = unmapnotify |
217 }; |
217 }; |
218 Atom wmatom[WMLast], netatom[NetLast]; |
218 Atom wmatom[WMLast], netatom[NetLast]; |
219 Bool otherwm, readin; |
219 Bool otherwm, readin; |
220 Bool running = True; |
220 Bool running = True; |
221 Bool *tagset[2]; |
221 unsigned int tagset[] = {1, 1}; /* after start, first tag is selected */ |
222 Client *clients = NULL; |
222 Client *clients = NULL; |
223 Client *sel = NULL; |
223 Client *sel = NULL; |
224 Client *stack = NULL; |
224 Client *stack = NULL; |
225 Cursor cursor[CurLast]; |
225 Cursor cursor[CurLast]; |
226 Display *dpy; |
226 Display *dpy; |
229 Layout *lt = layouts; |
229 Layout *lt = layouts; |
230 Window root, barwin; |
230 Window root, barwin; |
231 |
231 |
232 /* configuration, allows nested code to access above variables */ |
232 /* configuration, allows nested code to access above variables */ |
233 #include "config.h" |
233 #include "config.h" |
234 #define TAGSZ (LENGTH(tags) * sizeof(Bool)) |
234 |
235 /* check if all tags will fit into a unsigned int bitarray. */ |
|
236 static char tags_is_a_sign_that_your_IQ[sizeof(int) * 8 < LENGTH(tags) ? -1 : 1]; |
|
235 |
237 |
236 /* function implementations */ |
238 /* function implementations */ |
237 |
239 |
238 void |
240 void |
239 applyrules(Client *c) { |
241 applyrules(Client *c) { |
240 unsigned int i; |
242 unsigned int i; |
241 Bool matched = False; |
|
242 Rule *r; |
243 Rule *r; |
243 XClassHint ch = { 0 }; |
244 XClassHint ch = { 0 }; |
244 |
245 |
245 /* rule matching */ |
246 /* rule matching */ |
246 XGetClassHint(dpy, c->win, &ch); |
247 XGetClassHint(dpy, c->win, &ch); |
248 r = &rules[i]; |
249 r = &rules[i]; |
249 if((!r->title || strstr(c->name, r->title)) |
250 if((!r->title || strstr(c->name, r->title)) |
250 && (!r->class || (ch.res_class && strstr(ch.res_class, r->class))) |
251 && (!r->class || (ch.res_class && strstr(ch.res_class, r->class))) |
251 && (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) { |
252 && (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) { |
252 c->isfloating = r->isfloating; |
253 c->isfloating = r->isfloating; |
253 if(r->tag) { |
254 c->tags |= r->tags & TAGMASK; |
254 c->tags[idxoftag(r->tag)] = True; |
|
255 matched = True; |
|
256 } |
|
257 } |
255 } |
258 } |
256 } |
259 if(ch.res_class) |
257 if(ch.res_class) |
260 XFree(ch.res_class); |
258 XFree(ch.res_class); |
261 if(ch.res_name) |
259 if(ch.res_name) |
262 XFree(ch.res_name); |
260 XFree(ch.res_name); |
263 if(!matched) |
261 if(!c->tags) |
264 memcpy(c->tags, tagset[seltags], TAGSZ); |
262 c->tags = tagset[seltags]; |
265 } |
263 } |
266 |
264 |
267 void |
265 void |
268 arrange(void) { |
266 arrange(void) { |
269 Client *c; |
267 Client *c; |
305 c->isbanned = True; |
303 c->isbanned = True; |
306 } |
304 } |
307 |
305 |
308 void |
306 void |
309 buttonpress(XEvent *e) { |
307 buttonpress(XEvent *e) { |
310 unsigned int i, x; |
308 unsigned int i, x, mask; |
311 Client *c; |
309 Client *c; |
312 XButtonPressedEvent *ev = &e->xbutton; |
310 XButtonPressedEvent *ev = &e->xbutton; |
313 |
311 |
314 if(ev->window == barwin) { |
312 if(ev->window == barwin) { |
315 x = 0; |
313 x = 0; |
316 for(i = 0; i < LENGTH(tags); i++) { |
314 for(i = 0; i < LENGTH(tags); i++) { |
317 x += textw(tags[i]); |
315 x += textw(tags[i]); |
318 if(ev->x < x) { |
316 if(ev->x < x) { |
317 mask = 1 << i; |
|
319 if(ev->button == Button1) { |
318 if(ev->button == Button1) { |
320 if(ev->state & MODKEY) |
319 if(ev->state & MODKEY) |
321 tag(tags[i]); |
320 tag(&mask); |
322 else |
321 else |
323 view(tags[i]); |
322 view(&mask); |
324 } |
323 } |
325 else if(ev->button == Button3) { |
324 else if(ev->button == Button3) { |
326 if(ev->state & MODKEY) |
325 if(ev->state & MODKEY) |
327 toggletag(tags[i]); |
326 toggletag(&mask); |
328 else |
327 else |
329 toggleview(tags[i]); |
328 toggleview(&mask); |
330 } |
329 } |
331 return; |
330 return; |
332 } |
331 } |
333 } |
332 } |
334 if((ev->x < x + blw) && ev->button == Button1) |
333 if((ev->x < x + blw) && ev->button == Button1) |
499 |
498 |
500 dc.x = 0; |
499 dc.x = 0; |
501 for(c = stack; c && !isvisible(c); c = c->snext); |
500 for(c = stack; c && !isvisible(c); c = c->snext); |
502 for(i = 0; i < LENGTH(tags); i++) { |
501 for(i = 0; i < LENGTH(tags); i++) { |
503 dc.w = textw(tags[i]); |
502 dc.w = textw(tags[i]); |
504 if(tagset[seltags][i]) { |
503 if(tagset[seltags] & 1 << i) { |
505 drawtext(tags[i], dc.sel, isurgent(i)); |
504 drawtext(tags[i], dc.sel, isurgent(i)); |
506 drawsquare(c && c->tags[i], isoccupied(i), isurgent(i), dc.sel); |
505 drawsquare(c && c->tags & 1 << i, isoccupied(i), isurgent(i), dc.sel); |
507 } |
506 } |
508 else { |
507 else { |
509 drawtext(tags[i], dc.norm, isurgent(i)); |
508 drawtext(tags[i], dc.norm, isurgent(i)); |
510 drawsquare(c && c->tags[i], isoccupied(i), isurgent(i), dc.norm); |
509 drawsquare(c && c->tags & 1 << i, isoccupied(i), isurgent(i), dc.norm); |
511 } |
510 } |
512 dc.x += dc.w; |
511 dc.x += dc.w; |
513 } |
512 } |
514 if(blw > 0) { |
513 if(blw > 0) { |
515 dc.w = blw; |
514 dc.w = blw; |
666 if(sel && ev->window != sel->win) |
665 if(sel && ev->window != sel->win) |
667 XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime); |
666 XSetInputFocus(dpy, sel->win, RevertToPointerRoot, CurrentTime); |
668 } |
667 } |
669 |
668 |
670 void |
669 void |
671 focusnext(const char *arg) { |
670 focusnext(void *arg) { |
672 Client *c; |
671 Client *c; |
673 |
672 |
674 if(!sel) |
673 if(!sel) |
675 return; |
674 return; |
676 for(c = sel->next; c && !isvisible(c); c = c->next); |
675 for(c = sel->next; c && !isvisible(c); c = c->next); |
681 restack(); |
680 restack(); |
682 } |
681 } |
683 } |
682 } |
684 |
683 |
685 void |
684 void |
686 focusprev(const char *arg) { |
685 focusprev(void *arg) { |
687 Client *c; |
686 Client *c; |
688 |
687 |
689 if(!sel) |
688 if(!sel) |
690 return; |
689 return; |
691 for(c = sel->prev; c && !isvisible(c); c = c->prev); |
690 for(c = sel->prev; c && !isvisible(c); c = c->prev); |
806 XGrabKey(dpy, code, keys[i].mod|numlockmask|LockMask, root, True, |
805 XGrabKey(dpy, code, keys[i].mod|numlockmask|LockMask, root, True, |
807 GrabModeAsync, GrabModeAsync); |
806 GrabModeAsync, GrabModeAsync); |
808 } |
807 } |
809 } |
808 } |
810 |
809 |
811 unsigned int |
|
812 idxoftag(const char *t) { |
|
813 unsigned int i; |
|
814 |
|
815 for(i = 0; (i < LENGTH(tags)) && t && strcmp(tags[i], t); i++); |
|
816 return (i < LENGTH(tags)) ? i : 0; |
|
817 } |
|
818 |
|
819 void |
810 void |
820 initfont(const char *fontstr) { |
811 initfont(const char *fontstr) { |
821 char *def, **missing; |
812 char *def, **missing; |
822 int i, n; |
813 int i, n; |
823 |
814 |
859 Bool |
850 Bool |
860 isoccupied(unsigned int t) { |
851 isoccupied(unsigned int t) { |
861 Client *c; |
852 Client *c; |
862 |
853 |
863 for(c = clients; c; c = c->next) |
854 for(c = clients; c; c = c->next) |
864 if(c->tags[t]) |
855 if(c->tags & 1 << t) |
865 return True; |
856 return True; |
866 return False; |
857 return False; |
867 } |
858 } |
868 |
859 |
869 Bool |
860 Bool |
884 Bool |
875 Bool |
885 isurgent(unsigned int t) { |
876 isurgent(unsigned int t) { |
886 Client *c; |
877 Client *c; |
887 |
878 |
888 for(c = clients; c; c = c->next) |
879 for(c = clients; c; c = c->next) |
889 if(c->isurgent && c->tags[t]) |
880 if(c->isurgent && c->tags & 1 << t) |
890 return True; |
881 return True; |
891 return False; |
882 return False; |
892 } |
883 } |
893 |
884 |
894 Bool |
885 Bool |
895 isvisible(Client *c) { |
886 isvisible(Client *c) { |
896 unsigned int i; |
887 return c->tags & tagset[seltags]; |
897 |
|
898 for(i = 0; i < LENGTH(tags); i++) |
|
899 if(c->tags[i] && tagset[seltags][i]) |
|
900 return True; |
|
901 return False; |
|
902 } |
888 } |
903 |
889 |
904 void |
890 void |
905 keypress(XEvent *e) { |
891 keypress(XEvent *e) { |
906 unsigned int i; |
892 unsigned int i; |
917 keys[i].func(keys[i].arg); |
903 keys[i].func(keys[i].arg); |
918 } |
904 } |
919 } |
905 } |
920 |
906 |
921 void |
907 void |
922 killclient(const char *arg) { |
908 killclient(void *arg) { |
923 XEvent ev; |
909 XEvent ev; |
924 |
910 |
925 if(!sel) |
911 if(!sel) |
926 return; |
912 return; |
927 if(isprotodel(sel)) { |
913 if(isprotodel(sel)) { |
943 Status rettrans; |
929 Status rettrans; |
944 Window trans; |
930 Window trans; |
945 XWindowChanges wc; |
931 XWindowChanges wc; |
946 |
932 |
947 c = emallocz(sizeof(Client)); |
933 c = emallocz(sizeof(Client)); |
948 c->tags = emallocz(TAGSZ); |
|
949 c->win = w; |
934 c->win = w; |
950 |
935 |
951 /* geometry */ |
936 /* geometry */ |
952 c->x = wa->x; |
937 c->x = wa->x; |
953 c->y = wa->y; |
938 c->y = wa->y; |
978 grabbuttons(c, False); |
963 grabbuttons(c, False); |
979 updatetitle(c); |
964 updatetitle(c); |
980 if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) |
965 if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success)) |
981 for(t = clients; t && t->win != trans; t = t->next); |
966 for(t = clients; t && t->win != trans; t = t->next); |
982 if(t) |
967 if(t) |
983 memcpy(c->tags, t->tags, TAGSZ); |
968 c->tags = t->tags; |
984 else |
969 else |
985 applyrules(c); |
970 applyrules(c); |
986 if(!c->isfloating) |
971 if(!c->isfloating) |
987 c->isfloating = (rettrans == Success) || c->isfixed; |
972 c->isfloating = (rettrans == Success) || c->isfixed; |
988 attach(c); |
973 attach(c); |
1101 } |
1086 } |
1102 } |
1087 } |
1103 } |
1088 } |
1104 |
1089 |
1105 void |
1090 void |
1106 quit(const char *arg) { |
1091 quit(void *arg) { |
1107 readin = running = False; |
1092 readin = running = False; |
1108 } |
1093 } |
1109 |
1094 |
1110 void |
1095 void |
1111 resize(Client *c, int x, int y, int w, int h, Bool sizehints) { |
1096 resize(Client *c, int x, int y, int w, int h, Bool sizehints) { |
1332 |
1317 |
1333 XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, |
1318 XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, |
1334 PropModeReplace, (unsigned char *)data, 2); |
1319 PropModeReplace, (unsigned char *)data, 2); |
1335 } |
1320 } |
1336 |
1321 |
1337 void |
1322 /* arg > 1.0 will set mfact absolutly */ |
1338 setmfact(const char *arg) { |
1323 void |
1339 double d; |
1324 setmfact(void *arg) { |
1340 |
1325 double d = *((double*) arg); |
1341 if(!arg || lt->arrange != tile) |
1326 |
1327 if(!d || lt->arrange != tile) |
|
1342 return; |
1328 return; |
1343 else { |
1329 d = d < 1.0 ? d + mfact : d - 1.0; |
1344 d = strtod(arg, NULL); |
1330 if(d < 0.1 || d > 0.9) |
1345 if(arg[0] == '-' || arg[0] == '+') |
1331 return; |
1346 d += mfact; |
1332 mfact = d; |
1347 if(d < 0.1 || d > 0.9) |
|
1348 return; |
|
1349 mfact = d; |
|
1350 } |
|
1351 updatetilegeom(); |
1333 updatetilegeom(); |
1352 arrange(); |
1334 arrange(); |
1353 } |
1335 } |
1354 |
1336 |
1355 void |
1337 void |
1394 dc.gc = XCreateGC(dpy, root, 0, 0); |
1376 dc.gc = XCreateGC(dpy, root, 0, 0); |
1395 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); |
1377 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); |
1396 if(!dc.font.set) |
1378 if(!dc.font.set) |
1397 XSetFont(dpy, dc.gc, dc.font.xfont->fid); |
1379 XSetFont(dpy, dc.gc, dc.font.xfont->fid); |
1398 |
1380 |
1399 /* init tags */ |
|
1400 tagset[0] = emallocz(TAGSZ); |
|
1401 tagset[1] = emallocz(TAGSZ); |
|
1402 tagset[0][0] = tagset[1][0] = True; |
|
1403 |
|
1404 /* init bar */ |
1381 /* init bar */ |
1405 for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { |
1382 for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) { |
1406 w = textw(layouts[i].symbol); |
1383 w = textw(layouts[i].symbol); |
1407 blw = MAX(blw, w); |
1384 blw = MAX(blw, w); |
1408 } |
1385 } |
1433 /* grab keys */ |
1410 /* grab keys */ |
1434 grabkeys(); |
1411 grabkeys(); |
1435 } |
1412 } |
1436 |
1413 |
1437 void |
1414 void |
1438 spawn(const char *arg) { |
1415 spawn(void *arg) { |
1439 static char *shell = NULL; |
1416 static char *shell = NULL; |
1440 |
1417 |
1441 if(!shell && !(shell = getenv("SHELL"))) |
1418 if(!shell && !(shell = getenv("SHELL"))) |
1442 shell = "/bin/sh"; |
1419 shell = "/bin/sh"; |
1443 if(!arg) |
|
1444 return; |
|
1445 /* The double-fork construct avoids zombie processes and keeps the code |
1420 /* The double-fork construct avoids zombie processes and keeps the code |
1446 * clean from stupid signal handlers. */ |
1421 * clean from stupid signal handlers. */ |
1447 if(fork() == 0) { |
1422 if(fork() == 0) { |
1448 if(fork() == 0) { |
1423 if(fork() == 0) { |
1449 if(dpy) |
1424 if(dpy) |
1450 close(ConnectionNumber(dpy)); |
1425 close(ConnectionNumber(dpy)); |
1451 setsid(); |
1426 setsid(); |
1452 execl(shell, shell, "-c", arg, (char *)NULL); |
1427 execl(shell, shell, "-c", (char *)arg, (char *)NULL); |
1453 fprintf(stderr, "dwm: execl '%s -c %s'", shell, arg); |
1428 fprintf(stderr, "dwm: execl '%s -c %s'", shell, (char *)arg); |
1454 perror(" failed"); |
1429 perror(" failed"); |
1455 } |
1430 } |
1456 exit(0); |
1431 exit(0); |
1457 } |
1432 } |
1458 wait(0); |
1433 wait(0); |
1459 } |
1434 } |
1460 |
1435 |
1461 void |
1436 void |
1462 tag(const char *arg) { |
1437 tag(void *arg) { |
1463 unsigned int i; |
1438 if(sel && *(int *)arg & TAGMASK) { |
1464 |
1439 sel->tags = *(int *)arg & TAGMASK; |
1465 if(!sel) |
1440 arrange(); |
1466 return; |
1441 } |
1467 for(i = 0; i < LENGTH(tags); i++) |
|
1468 sel->tags[i] = (arg == NULL); |
|
1469 sel->tags[idxoftag(arg)] = True; |
|
1470 arrange(); |
|
1471 } |
1442 } |
1472 |
1443 |
1473 unsigned int |
1444 unsigned int |
1474 textnw(const char *text, unsigned int len) { |
1445 textnw(const char *text, unsigned int len) { |
1475 XRectangle r; |
1446 XRectangle r; |
1532 /* client doesn't accept size constraints */ |
1503 /* client doesn't accept size constraints */ |
1533 resize(c, x, y, w, h, False); |
1504 resize(c, x, y, w, h, False); |
1534 } |
1505 } |
1535 |
1506 |
1536 void |
1507 void |
1537 togglebar(const char *arg) { |
1508 togglebar(void *arg) { |
1538 showbar = !showbar; |
1509 showbar = !showbar; |
1539 updategeom(); |
1510 updategeom(); |
1540 updatebar(); |
1511 updatebar(); |
1541 arrange(); |
1512 arrange(); |
1542 } |
1513 } |
1543 |
1514 |
1544 void |
1515 void |
1545 togglefloating(const char *arg) { |
1516 togglefloating(void *arg) { |
1546 if(!sel) |
1517 if(!sel) |
1547 return; |
1518 return; |
1548 sel->isfloating = !sel->isfloating; |
1519 sel->isfloating = !sel->isfloating; |
1549 if(sel->isfloating) |
1520 if(sel->isfloating) |
1550 resize(sel, sel->x, sel->y, sel->w, sel->h, True); |
1521 resize(sel, sel->x, sel->y, sel->w, sel->h, True); |
1551 arrange(); |
1522 arrange(); |
1552 } |
1523 } |
1553 |
1524 |
1554 void |
1525 void |
1555 togglelayout(const char *arg) { |
1526 togglelayout(void *arg) { |
1556 unsigned int i; |
1527 unsigned int i; |
1557 |
1528 |
1558 if(!arg) { |
1529 if(!arg) { |
1559 if(++lt == &layouts[LENGTH(layouts)]) |
1530 if(++lt == &layouts[LENGTH(layouts)]) |
1560 lt = &layouts[0]; |
1531 lt = &layouts[0]; |
1561 } |
1532 } |
1562 else { |
1533 else { |
1563 for(i = 0; i < LENGTH(layouts); i++) |
1534 for(i = 0; i < LENGTH(layouts); i++) |
1564 if(!strcmp(arg, layouts[i].symbol)) |
1535 if(!strcmp((char *)arg, layouts[i].symbol)) |
1565 break; |
1536 break; |
1566 if(i == LENGTH(layouts)) |
1537 if(i == LENGTH(layouts)) |
1567 return; |
1538 return; |
1568 lt = &layouts[i]; |
1539 lt = &layouts[i]; |
1569 } |
1540 } |
1572 else |
1543 else |
1573 drawbar(); |
1544 drawbar(); |
1574 } |
1545 } |
1575 |
1546 |
1576 void |
1547 void |
1577 toggletag(const char *arg) { |
1548 toggletag(void *arg) { |
1578 unsigned int i, j; |
1549 int i, m = *(int *)arg; |
1579 |
1550 for(i = 0; i < sizeof(int) * 8; i++) |
1580 if(!sel) |
1551 fputc(m & 1 << i ? '1' : '0', stdout); |
1581 return; |
1552 puts(""); |
1582 i = idxoftag(arg); |
1553 for(i = 0; i < sizeof(int) * 8; i++) |
1583 sel->tags[i] = !sel->tags[i]; |
1554 fputc(TAGMASK & 1 << i ? '1' : '0', stdout); |
1584 for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++); |
1555 puts("aaa"); |
1585 if(j == LENGTH(tags)) |
1556 |
1586 sel->tags[i] = True; /* at least one tag must be enabled */ |
1557 if(sel && (sel->tags ^ ((*(int *)arg) & TAGMASK))) { |
1587 arrange(); |
1558 sel->tags ^= (*(int *)arg) & TAGMASK; |
1588 } |
1559 arrange(); |
1589 |
1560 } |
1590 void |
1561 } |
1591 toggleview(const char *arg) { |
1562 |
1592 unsigned int i, j; |
1563 void |
1593 |
1564 toggleview(void *arg) { |
1594 i = idxoftag(arg); |
1565 if((tagset[seltags] ^ ((*(int *)arg) & TAGMASK))) { |
1595 tagset[seltags][i] = !tagset[seltags][i]; |
1566 tagset[seltags] ^= (*(int *)arg) & TAGMASK; |
1596 for(j = 0; j < LENGTH(tags) && !tagset[seltags][j]; j++); |
1567 arrange(); |
1597 if(j == LENGTH(tags)) |
1568 } |
1598 tagset[seltags][i] = True; /* at least one tag must be viewed */ |
|
1599 arrange(); |
|
1600 } |
1569 } |
1601 |
1570 |
1602 void |
1571 void |
1603 unban(Client *c) { |
1572 unban(Client *c) { |
1604 if(!c->isbanned) |
1573 if(!c->isbanned) |
1620 detachstack(c); |
1589 detachstack(c); |
1621 if(sel == c) |
1590 if(sel == c) |
1622 focus(NULL); |
1591 focus(NULL); |
1623 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
1592 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
1624 setclientstate(c, WithdrawnState); |
1593 setclientstate(c, WithdrawnState); |
1625 free(c->tags); |
|
1626 free(c); |
1594 free(c); |
1627 XSync(dpy, False); |
1595 XSync(dpy, False); |
1628 XSetErrorHandler(xerror); |
1596 XSetErrorHandler(xerror); |
1629 XUngrabServer(dpy); |
1597 XUngrabServer(dpy); |
1630 arrange(); |
1598 arrange(); |
1767 XFree(wmh); |
1735 XFree(wmh); |
1768 } |
1736 } |
1769 } |
1737 } |
1770 |
1738 |
1771 void |
1739 void |
1772 view(const char *arg) { |
1740 view(void *arg) { |
1773 seltags ^= 1; /* toggle sel tagset */ |
1741 if(*(int *)arg & TAGMASK) { |
1774 memset(tagset[seltags], (NULL == arg), TAGSZ); |
1742 seltags ^= 1; /* toggle sel tagset */ |
1775 tagset[seltags][idxoftag(arg)] = True; |
1743 tagset[seltags] = *(int *)arg & TAGMASK; |
1776 arrange(); |
1744 arrange(); |
1777 } |
1745 } |
1778 |
1746 } |
1779 void |
1747 |
1780 viewprevtag(const char *arg) { |
1748 void |
1749 viewprevtag(void *arg) { |
|
1781 seltags ^= 1; /* toggle sel tagset */ |
1750 seltags ^= 1; /* toggle sel tagset */ |
1782 arrange(); |
1751 arrange(); |
1783 } |
1752 } |
1784 |
1753 |
1785 /* There's no way to check accesses to destroyed windows, thus those cases are |
1754 /* There's no way to check accesses to destroyed windows, thus those cases are |
1814 otherwm = True; |
1783 otherwm = True; |
1815 return -1; |
1784 return -1; |
1816 } |
1785 } |
1817 |
1786 |
1818 void |
1787 void |
1819 zoom(const char *arg) { |
1788 zoom(void *arg) { |
1820 Client *c = sel; |
1789 Client *c = sel; |
1821 |
1790 |
1822 if(c == nextunfloating(clients)) |
1791 if(c == nextunfloating(clients)) |
1823 if(!c || !(c = nextunfloating(c->next))) |
1792 if(!c || !(c = nextunfloating(c->next))) |
1824 return; |
1793 return; |